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

View File

@ -1,6 +1,6 @@
import { isNativeTerra } from "@certusone/wormhole-sdk";
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 { TerraTokenMetadata } from "../hooks/useTerraTokenMap";
import { TERRA_HOST } from "./consts";
@ -37,3 +37,24 @@ export async function waitForTerraExecution(transaction: TxResult) {
}
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,
tokenAddress: string,
amount: string,
taxed: string,
recipientChain: ChainId,
recipientAddress: Uint8Array
) {
@ -108,7 +109,7 @@ export async function transferFromTerra(
{
initiate_transfer: {
asset: {
amount: amount,
amount: taxed,
info: {
native_token: {
denom: tokenAddress,

View File

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

View File

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