terra/token_bridge: subtract tax from deposited tokens

Change-Id: Ib1647a4b3757054fc91fe4dd51317a5095a526a2
This commit is contained in:
Reisen 2021-10-04 11:52:11 +00:00 committed by David Paryente
parent 56c1b43280
commit d2c976b04c
5 changed files with 48 additions and 14 deletions

View File

@ -58,7 +58,7 @@ import {
import { getSignedVAAWithRetry } from "../utils/getSignedVAAWithRetry"; import { getSignedVAAWithRetry } from "../utils/getSignedVAAWithRetry";
import parseError from "../utils/parseError"; import parseError from "../utils/parseError";
import { signSendAndConfirm } from "../utils/solana"; import { signSendAndConfirm } from "../utils/solana";
import { waitForTerraExecution } from "../utils/terra"; import { waitForTerraExecution, calculateTerraTax } from "../utils/terra";
import useTransferTargetAddressHex from "./useTransferTargetAddress"; import useTransferTargetAddressHex from "./useTransferTargetAddress";
async function eth( async function eth(
@ -198,11 +198,13 @@ async function terra(
dispatch(setIsSending(true)); dispatch(setIsSending(true));
try { try {
const amountParsed = parseUnits(amount, decimals).toString(); const amountParsed = parseUnits(amount, decimals).toString();
const amountTaxed = await calculateTerraTax(amountParsed, asset);
const msgs = await transferFromTerra( const msgs = await transferFromTerra(
wallet.terraAddress, wallet.terraAddress,
TERRA_TOKEN_BRIDGE_ADDRESS, TERRA_TOKEN_BRIDGE_ADDRESS,
asset, asset,
amountParsed, amountParsed,
amountTaxed,
targetChain, targetChain,
targetAddress targetAddress
); );

View File

@ -1,6 +1,6 @@
import { isNativeTerra } from "@certusone/wormhole-sdk"; import { isNativeTerra } from "@certusone/wormhole-sdk";
import { formatUnits } from "@ethersproject/units"; import { formatUnits } from "@ethersproject/units";
import { LCDClient } from "@terra-money/terra.js"; import { LCDClient, Dec, Int } from "@terra-money/terra.js";
import { TxResult } from "@terra-money/wallet-provider"; import { TxResult } from "@terra-money/wallet-provider";
// import { TerraTokenMetadata } from "../hooks/useTerraTokenMap"; // import { TerraTokenMetadata } from "../hooks/useTerraTokenMap";
import { TERRA_HOST } from "./consts"; import { TERRA_HOST } from "./consts";
@ -37,3 +37,24 @@ export async function waitForTerraExecution(transaction: TxResult) {
} }
return info; return info;
} }
export async function calculateTerraTax(
amount: string,
denom: string
): Promise<string> {
try {
// Fetch terra tax state from current chain height.
const lcd = new LCDClient(TERRA_HOST);
const taxRate = await lcd.treasury.taxRate();
const taxCap = await lcd.treasury.taxCap(denom);
// Calculate tax rate for the current denomination.
const untaxed = new Int(amount);
const tax = untaxed.toDec().mul(taxRate);
const cap = (taxCap.amount as Int).toDec();
const min = new Dec((tax.constructor as any).min(tax, cap));
return untaxed.sub(min.toInt()).toString();
} catch(e) {
return "0";
}
}

View File

@ -87,6 +87,7 @@ export async function transferFromTerra(
tokenBridgeAddress: string, tokenBridgeAddress: string,
tokenAddress: string, tokenAddress: string,
amount: string, amount: string,
taxed: string,
recipientChain: ChainId, recipientChain: ChainId,
recipientAddress: Uint8Array recipientAddress: Uint8Array
) { ) {
@ -108,7 +109,7 @@ export async function transferFromTerra(
{ {
initiate_transfer: { initiate_transfer: {
asset: { asset: {
amount: amount, amount: taxed,
info: { info: {
native_token: { native_token: {
denom: tokenAddress, denom: tokenAddress,

View File

@ -2,6 +2,7 @@ use cosmwasm_std::{
Binary, Binary,
Uint128, Uint128,
}; };
use terraswap::asset::{Asset, AssetInfo};
use schemars::JsonSchema; use schemars::JsonSchema;
use serde::{ use serde::{
Deserialize, Deserialize,
@ -27,9 +28,14 @@ pub enum ExecuteMsg {
asset_id: Binary, asset_id: Binary,
}, },
DepositTokens {},
WithdrawTokens {
asset: AssetInfo,
},
InitiateTransfer { InitiateTransfer {
asset: HumanAddr, asset: Asset,
amount: Uint128,
recipient_chain: u16, recipient_chain: u16,
recipient: Binary, recipient: Binary,
fee: Uint128, fee: Uint128,
@ -41,7 +47,7 @@ pub enum ExecuteMsg {
}, },
CreateAssetMeta { CreateAssetMeta {
asset_address: HumanAddr, asset_info: AssetInfo,
nonce: u32, nonce: u32,
}, },
} }

View File

@ -193,14 +193,18 @@ fn deposit_tokens<S: Storage, A: Api, Q: Querier>(
deps: &mut Extern<S, A, Q>, deps: &mut Extern<S, A, Q>,
env: Env, env: Env,
) -> StdResult<HandleResponse> { ) -> StdResult<HandleResponse> {
for fund in env.message.sent_funds { for coin in env.message.sent_funds {
let deposit_key = format!("{}:{}", env.message.sender, fund.denom); let asset = Asset {
bridge_deposit(&mut deps.storage).update(deposit_key.as_bytes(), |amount: Option<Uint128>| { amount: coin.amount.clone(),
match amount { info: AssetInfo::NativeToken {
Some(v) => Ok(v + fund.amount), denom: coin.denom.clone(),
None => Ok(fund.amount) },
} };
})?; let deducted_amount = asset.deduct_tax(&deps)?.amount;
let deposit_key = format!("{}:{}", env.message.sender, coin.denom);
bridge_deposit(&mut deps.storage).update(deposit_key.as_bytes(), |amount: Option<Uint128>|
Ok(amount.unwrap_or(Uint128(0)) + deducted_amount)
)?;
} }
Ok(HandleResponse { Ok(HandleResponse {