Skip to content

Commit 7c3dbb0

Browse files
authored
Merge pull request #8 from choice-exchange/aggregation_contract_support
transfer admin functions
2 parents 9e21763 + 2262c6e commit 7c3dbb0

5 files changed

Lines changed: 168 additions & 130 deletions

File tree

‎README.md‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ As much as possible, the original CW20 standard has been left untouched. Instead
1212

1313
## Design
1414

15-
The standard has been built in a way to utilise 2 contracts:
15+
The standard has been built in a way to utilize 2 contracts:
1616

1717
- Reflection treasury: Any reflection and taxes are processed in the treasury contract. The CW20 Taxed Token is the owner of the treasury. Developers are able to retrieve the reflected amounts out of the treasury, and separately airdrop the amounts to their users.
1818
- CW20 Taxed Token: This contract is a modified version of the CW20 to allow tax-on-transfer to happen. All `ExecuteMsg` and `QueryMsg` are preserved. Additional function signatures have been added to cater for the taxation logic.
@@ -159,4 +159,3 @@ Finally, you must tell the Treasury which liquidity pools to use for its operati
159159
}
160160
}
161161
```
162-

‎contracts/cw20_reflection_token/src/contract.rs‎

Lines changed: 145 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,138 @@ pub fn instantiate(
130130
)))
131131
}
132132

133+
#[cfg_attr(not(feature = "library"), entry_point)]
134+
pub fn execute(
135+
deps: DepsMut,
136+
env: Env,
137+
info: MessageInfo,
138+
msg: ExecuteMsg,
139+
) -> Result<Response, ContractError> {
140+
match msg {
141+
ExecuteMsg::Transfer { recipient, amount } => {
142+
execute_transfer(deps, env, info, recipient, amount)
143+
}
144+
ExecuteMsg::Burn { amount } => execute_burn(deps, env, info, amount),
145+
ExecuteMsg::Send {
146+
contract,
147+
amount,
148+
msg,
149+
} => execute_send(deps, env, info, contract, amount, msg),
150+
ExecuteMsg::Mint { recipient, amount } => execute_mint(deps, env, info, recipient, amount),
151+
ExecuteMsg::IncreaseAllowance {
152+
spender,
153+
amount,
154+
expires,
155+
} => execute_increase_allowance(deps, env, info, spender, amount, expires),
156+
ExecuteMsg::DecreaseAllowance {
157+
spender,
158+
amount,
159+
expires,
160+
} => execute_decrease_allowance(deps, env, info, spender, amount, expires),
161+
ExecuteMsg::TransferFrom {
162+
owner,
163+
recipient,
164+
amount,
165+
} => execute_transfer_from(deps, env, info, owner, recipient, amount),
166+
ExecuteMsg::BurnFrom { owner, amount } => execute_burn_from(deps, env, info, owner, amount),
167+
ExecuteMsg::SendFrom {
168+
owner,
169+
contract,
170+
amount,
171+
msg,
172+
} => execute_send_from(deps, env, info, owner, contract, amount, msg),
173+
ExecuteMsg::UpdateMarketing {
174+
project,
175+
description,
176+
marketing,
177+
} => execute_update_marketing(deps, env, info, project, description, marketing),
178+
ExecuteMsg::UploadLogo(logo) => execute_upload_logo(deps, env, info, logo),
179+
180+
// Reflection features
181+
ExecuteMsg::SetWhitelist { user, enable } => set_whitelist(deps, info, user, enable),
182+
ExecuteMsg::SetTaxRate {
183+
global_rate,
184+
reflection_rate,
185+
burn_rate,
186+
antiwhale_rate,
187+
} => set_tax_rate(
188+
deps,
189+
env,
190+
info,
191+
global_rate,
192+
reflection_rate,
193+
burn_rate,
194+
antiwhale_rate,
195+
),
196+
ExecuteMsg::TransferEvent { from, to, amount } => {
197+
generate_transfer_event(deps, info, env, from, to, amount)
198+
}
199+
ExecuteMsg::MigrateTreasury { code_id } => migrate_treasury(deps, env, info, code_id),
200+
201+
// admin add an remove trusted aggregator contracts
202+
ExecuteMsg::AddAggregator { address } => add_aggregator(deps, info, address),
203+
ExecuteMsg::RemoveAggregator { address } => remove_aggregator(deps, info, address),
204+
205+
// allow aggregation contracts to do tax free transfers
206+
ExecuteMsg::TaxExemptTransfer { recipient, amount } => {
207+
if !AGGREGATORS.has(deps.storage, &info.sender) {
208+
return Err(ContractError::Unauthorized {});
209+
}
210+
execute_transfer_tax_exempt(deps, info, recipient, amount)
211+
}
212+
ExecuteMsg::TaxExemptSend {
213+
contract,
214+
amount,
215+
msg,
216+
} => {
217+
if !AGGREGATORS.has(deps.storage, &info.sender) {
218+
return Err(ContractError::Unauthorized {});
219+
}
220+
execute_send_tax_exempt(deps, info, contract, amount, msg)
221+
}
222+
223+
// To enable tax free liquidity provision
224+
ExecuteMsg::AddTransferFromRecipient { address } => {
225+
add_transfer_from_recipient(deps, info, address)
226+
}
227+
ExecuteMsg::RemoveTransferFromRecipient { address } => {
228+
remove_transfer_from_recipient(deps, info, address)
229+
}
230+
231+
ExecuteMsg::TransferAdmin { new_admin } => {
232+
transfer_admin(deps, info, new_admin)
233+
}
234+
}
235+
}
236+
237+
#[cfg_attr(not(feature = "library"), entry_point)]
238+
pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult<Binary> {
239+
match msg {
240+
QueryMsg::Balance { address } => to_json_binary(&query_balance(deps, address)?),
241+
QueryMsg::TokenInfo {} => to_json_binary(&query_token_info(deps)?),
242+
QueryMsg::Minter {} => to_json_binary(&query_minter(deps)?),
243+
QueryMsg::Allowance { owner, spender } => {
244+
to_json_binary(&query_allowance(deps, owner, spender)?)
245+
}
246+
QueryMsg::AllAllowances {
247+
owner,
248+
start_after,
249+
limit,
250+
} => to_json_binary(&query_owner_allowances(deps, owner, start_after, limit)?),
251+
QueryMsg::AllAccounts { start_after, limit } => {
252+
to_json_binary(&query_all_accounts(deps, start_after, limit)?)
253+
}
254+
QueryMsg::MarketingInfo {} => to_json_binary(&query_marketing_info(deps)?),
255+
QueryMsg::DownloadLogo {} => to_json_binary(&query_download_logo(deps)?),
256+
QueryMsg::QueryTax { amount } => to_json_binary(&query_tax(deps.storage, amount)?),
257+
QueryMsg::QueryRates {} => to_json_binary(&query_rate(deps.storage)?),
258+
QueryMsg::GetWhitelist { address } => {
259+
to_json_binary(&query_whitelist(deps.storage, address)?)
260+
}
261+
QueryMsg::GetTreasury {} => to_json_binary(&query_treasury(deps.storage)?),
262+
}
263+
}
264+
133265
/// Unwrap a `Reply` object to extract the response
134266
pub fn unwrap_reply(reply: Reply) -> StdResult<SubMsgResponse> {
135267
reply.result.into_result().map_err(StdError::generic_err)
@@ -143,6 +275,19 @@ pub fn reply(deps: DepsMut, _env: Env, reply: Reply) -> Result<Response, Contrac
143275
}
144276
}
145277

278+
pub fn transfer_admin(
279+
deps: DepsMut,
280+
info: MessageInfo,
281+
new_admin: String,
282+
) -> Result<Response, ContractError> {
283+
ensure_admin(&deps, &info)?;
284+
let new_admin_addr = deps.api.addr_validate(&new_admin)?;
285+
ADMIN.save(deps.storage, &new_admin_addr.to_string())?;
286+
Ok(Response::new()
287+
.add_attribute("action", "transfer_admin")
288+
.add_attribute("new_admin", new_admin))
289+
}
290+
146291
/// Standard CW20 transfer function that is modified to include tax functions, and anti-whale feature
147292
/// These modifications are all applied to the `transfer`, `send`, `transfer_from`, and `send_from` functions
148293
pub fn execute_transfer(
@@ -593,134 +738,6 @@ pub fn remove_transfer_from_recipient(
593738
.add_attribute("address", address))
594739
}
595740

596-
#[cfg_attr(not(feature = "library"), entry_point)]
597-
pub fn execute(
598-
deps: DepsMut,
599-
env: Env,
600-
info: MessageInfo,
601-
msg: ExecuteMsg,
602-
) -> Result<Response, ContractError> {
603-
match msg {
604-
ExecuteMsg::Transfer { recipient, amount } => {
605-
execute_transfer(deps, env, info, recipient, amount)
606-
}
607-
ExecuteMsg::Burn { amount } => execute_burn(deps, env, info, amount),
608-
ExecuteMsg::Send {
609-
contract,
610-
amount,
611-
msg,
612-
} => execute_send(deps, env, info, contract, amount, msg),
613-
ExecuteMsg::Mint { recipient, amount } => execute_mint(deps, env, info, recipient, amount),
614-
ExecuteMsg::IncreaseAllowance {
615-
spender,
616-
amount,
617-
expires,
618-
} => execute_increase_allowance(deps, env, info, spender, amount, expires),
619-
ExecuteMsg::DecreaseAllowance {
620-
spender,
621-
amount,
622-
expires,
623-
} => execute_decrease_allowance(deps, env, info, spender, amount, expires),
624-
ExecuteMsg::TransferFrom {
625-
owner,
626-
recipient,
627-
amount,
628-
} => execute_transfer_from(deps, env, info, owner, recipient, amount),
629-
ExecuteMsg::BurnFrom { owner, amount } => execute_burn_from(deps, env, info, owner, amount),
630-
ExecuteMsg::SendFrom {
631-
owner,
632-
contract,
633-
amount,
634-
msg,
635-
} => execute_send_from(deps, env, info, owner, contract, amount, msg),
636-
ExecuteMsg::UpdateMarketing {
637-
project,
638-
description,
639-
marketing,
640-
} => execute_update_marketing(deps, env, info, project, description, marketing),
641-
ExecuteMsg::UploadLogo(logo) => execute_upload_logo(deps, env, info, logo),
642-
643-
// Reflection features
644-
ExecuteMsg::SetWhitelist { user, enable } => set_whitelist(deps, info, user, enable),
645-
ExecuteMsg::SetTaxRate {
646-
global_rate,
647-
reflection_rate,
648-
burn_rate,
649-
antiwhale_rate,
650-
} => set_tax_rate(
651-
deps,
652-
env,
653-
info,
654-
global_rate,
655-
reflection_rate,
656-
burn_rate,
657-
antiwhale_rate,
658-
),
659-
ExecuteMsg::TransferEvent { from, to, amount } => {
660-
generate_transfer_event(deps, info, env, from, to, amount)
661-
}
662-
ExecuteMsg::MigrateTreasury { code_id } => migrate_treasury(deps, env, info, code_id),
663-
664-
// admin add an remove trusted aggregator contracts
665-
ExecuteMsg::AddAggregator { address } => add_aggregator(deps, info, address),
666-
ExecuteMsg::RemoveAggregator { address } => remove_aggregator(deps, info, address),
667-
668-
// allow aggregation contracts to do tax free transfers
669-
ExecuteMsg::TaxExemptTransfer { recipient, amount } => {
670-
if !AGGREGATORS.has(deps.storage, &info.sender) {
671-
return Err(ContractError::Unauthorized {});
672-
}
673-
execute_transfer_tax_exempt(deps, info, recipient, amount)
674-
}
675-
ExecuteMsg::TaxExemptSend {
676-
contract,
677-
amount,
678-
msg,
679-
} => {
680-
if !AGGREGATORS.has(deps.storage, &info.sender) {
681-
return Err(ContractError::Unauthorized {});
682-
}
683-
execute_send_tax_exempt(deps, info, contract, amount, msg)
684-
}
685-
686-
// To enable tax free liquidity provision
687-
ExecuteMsg::AddTransferFromRecipient { address } => {
688-
add_transfer_from_recipient(deps, info, address)
689-
}
690-
ExecuteMsg::RemoveTransferFromRecipient { address } => {
691-
remove_transfer_from_recipient(deps, info, address)
692-
}
693-
}
694-
}
695-
696-
#[cfg_attr(not(feature = "library"), entry_point)]
697-
pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult<Binary> {
698-
match msg {
699-
QueryMsg::Balance { address } => to_json_binary(&query_balance(deps, address)?),
700-
QueryMsg::TokenInfo {} => to_json_binary(&query_token_info(deps)?),
701-
QueryMsg::Minter {} => to_json_binary(&query_minter(deps)?),
702-
QueryMsg::Allowance { owner, spender } => {
703-
to_json_binary(&query_allowance(deps, owner, spender)?)
704-
}
705-
QueryMsg::AllAllowances {
706-
owner,
707-
start_after,
708-
limit,
709-
} => to_json_binary(&query_owner_allowances(deps, owner, start_after, limit)?),
710-
QueryMsg::AllAccounts { start_after, limit } => {
711-
to_json_binary(&query_all_accounts(deps, start_after, limit)?)
712-
}
713-
QueryMsg::MarketingInfo {} => to_json_binary(&query_marketing_info(deps)?),
714-
QueryMsg::DownloadLogo {} => to_json_binary(&query_download_logo(deps)?),
715-
QueryMsg::QueryTax { amount } => to_json_binary(&query_tax(deps.storage, amount)?),
716-
QueryMsg::QueryRates {} => to_json_binary(&query_rate(deps.storage)?),
717-
QueryMsg::GetWhitelist { address } => {
718-
to_json_binary(&query_whitelist(deps.storage, address)?)
719-
}
720-
QueryMsg::GetTreasury {} => to_json_binary(&query_treasury(deps.storage)?),
721-
}
722-
}
723-
724741
pub fn query_treasury(storage: &dyn Storage) -> Result<GetTreasuryResponse, StdError> {
725742
let treasury_addr = TREASURY.load(storage)?;
726743
Ok(GetTreasuryResponse {

‎contracts/cw20_reflection_token/src/msg.rs‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,9 @@ pub enum ExecuteMsg {
155155
RemoveTransferFromRecipient {
156156
address: String,
157157
},
158+
TransferAdmin {
159+
new_admin: String,
160+
},
158161
}
159162

160163
impl InstantiateMsg {

‎contracts/cw20_reflection_treasury/src/contract.rs‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,25 @@ pub fn execute(
7979
}
8080
ExecuteMsg::Liquify {} => liquify_treasury(&deps.querier, env, deps.storage),
8181
ExecuteMsg::WithdrawToken { asset } => withdraw_token(deps, env, info, asset),
82+
ExecuteMsg::TransferAdmin { new_admin } => {
83+
transfer_admin(deps, info, new_admin)
84+
}
8285
}
8386
}
8487

88+
pub fn transfer_admin(
89+
deps: DepsMut,
90+
info: MessageInfo,
91+
new_admin: String,
92+
) -> Result<Response, ContractError> {
93+
ensure_admin(&deps, &info)?;
94+
let new_admin_addr = deps.api.addr_validate(&new_admin)?;
95+
ADMIN.save(deps.storage, &new_admin_addr.to_string())?;
96+
Ok(Response::new()
97+
.add_attribute("action", "transfer_admin")
98+
.add_attribute("new_admin", new_admin))
99+
}
100+
85101
#[cfg_attr(not(feature = "library"), entry_point)]
86102
pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult<Binary> {
87103
match msg {

‎contracts/cw20_reflection_treasury/src/msg.rs‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ pub enum ExecuteMsg {
3131
asset: AssetInfo,
3232
},
3333
Liquify {},
34+
TransferAdmin {
35+
new_admin: String,
36+
},
3437
}
3538

3639
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]

0 commit comments

Comments
 (0)