ethereum: truncate decimals to 9
This commit is contained in:
parent
a1387dafea
commit
a2bd5fbb11
|
@ -19,6 +19,8 @@ contract Wormhole is ReentrancyGuard {
|
||||||
using BytesLib for bytes;
|
using BytesLib for bytes;
|
||||||
using SafeMath for uint256;
|
using SafeMath for uint256;
|
||||||
|
|
||||||
|
uint64 constant MAX_UINT64 = 18_446_744_073_709_551_615;
|
||||||
|
|
||||||
// Address of the Wrapped asset template
|
// Address of the Wrapped asset template
|
||||||
address public wrappedAssetMaster;
|
address public wrappedAssetMaster;
|
||||||
|
|
||||||
|
@ -207,12 +209,15 @@ contract Wormhole is ReentrancyGuard {
|
||||||
uint256 amount,
|
uint256 amount,
|
||||||
bytes32 recipient,
|
bytes32 recipient,
|
||||||
uint8 target_chain,
|
uint8 target_chain,
|
||||||
uint32 nonce
|
uint32 nonce,
|
||||||
|
bool refund_dust
|
||||||
) public nonReentrant {
|
) public nonReentrant {
|
||||||
require(amount != 0, "amount must not be 0");
|
require(amount != 0, "amount must not be 0");
|
||||||
|
|
||||||
uint8 asset_chain = CHAIN_ID;
|
uint8 asset_chain = CHAIN_ID;
|
||||||
bytes32 asset_address;
|
bytes32 asset_address;
|
||||||
|
uint8 decimals = ERC20(asset).decimals();
|
||||||
|
|
||||||
if (isWrappedAsset[asset]) {
|
if (isWrappedAsset[asset]) {
|
||||||
WrappedAsset(asset).burn(msg.sender, amount);
|
WrappedAsset(asset).burn(msg.sender, amount);
|
||||||
asset_chain = WrappedAsset(asset).assetChain();
|
asset_chain = WrappedAsset(asset).assetChain();
|
||||||
|
@ -225,10 +230,25 @@ contract Wormhole is ReentrancyGuard {
|
||||||
// The amount that was transferred in is the delta between balance before and after the transfer.
|
// The amount that was transferred in is the delta between balance before and after the transfer.
|
||||||
// This is to properly handle tokens that charge a fee on transfer.
|
// This is to properly handle tokens that charge a fee on transfer.
|
||||||
amount = balanceAfter.sub(balanceBefore);
|
amount = balanceAfter.sub(balanceBefore);
|
||||||
|
|
||||||
|
// Decimal adjust amount - we keep the dust
|
||||||
|
if (decimals > 9) {
|
||||||
|
uint256 original_amount = amount;
|
||||||
|
amount = amount.div(10 ** uint256(decimals - 9));
|
||||||
|
|
||||||
|
if (refund_dust) {
|
||||||
|
ERC20(asset).transfer(msg.sender, original_amount.mod(10 ** uint256(decimals - 9)));
|
||||||
|
}
|
||||||
|
|
||||||
|
decimals = 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
require(balanceAfter.div(10 ** uint256(ERC20(asset).decimals() - 9)) <= MAX_UINT64, "bridge balance would exceed maximum");
|
||||||
|
|
||||||
asset_address = bytes32(uint256(asset));
|
asset_address = bytes32(uint256(asset));
|
||||||
}
|
}
|
||||||
|
|
||||||
emit LogTokensLocked(target_chain, asset_chain, ERC20(asset).decimals(), asset_address, bytes32(uint256(msg.sender)), recipient, amount, nonce);
|
emit LogTokensLocked(target_chain, asset_chain, decimals, asset_address, bytes32(uint256(msg.sender)), recipient, amount, nonce);
|
||||||
}
|
}
|
||||||
|
|
||||||
function lockETH(
|
function lockETH(
|
||||||
|
@ -245,14 +265,14 @@ contract Wormhole is ReentrancyGuard {
|
||||||
emit LogTokensLocked(target_chain, CHAIN_ID, 18, bytes32(uint256(WETHAddress)), bytes32(uint256(msg.sender)), recipient, msg.value, nonce);
|
emit LogTokensLocked(target_chain, CHAIN_ID, 18, bytes32(uint256(WETHAddress)), bytes32(uint256(msg.sender)), recipient, msg.value, nonce);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fallback() external payable {revert("please use lockETH to transfer ETH to Solana");}
|
||||||
|
|
||||||
fallback() external payable {revert("please use lockETH to transfer ETH to Solana");}
|
receive() external payable {revert("please use lockETH to transfer ETH to Solana");}
|
||||||
receive() external payable {revert("please use lockETH to transfer ETH to Solana");}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
interface WETH is IERC20 {
|
interface WETH is IERC20 {
|
||||||
function deposit() external payable;
|
function deposit() external payable;
|
||||||
|
|
||||||
function withdraw(uint256 amount) external;
|
function withdraw(uint256 amount) external;
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,7 +87,7 @@ contract("Wormhole", function () {
|
||||||
// Expect user to have a balance
|
// Expect user to have a balance
|
||||||
let wa = new WrappedAsset("0xC3697aaf5B3D354214548248710414812099bc93")
|
let wa = new WrappedAsset("0xC3697aaf5B3D354214548248710414812099bc93")
|
||||||
|
|
||||||
await bridge.lockAssets(wa.address, "500000000000000000", "0x0", 2, 2);
|
await bridge.lockAssets(wa.address, "500000000000000000", "0x0", 2, 2, false);
|
||||||
let balance = await wa.balanceOf("0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1");
|
let balance = await wa.balanceOf("0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1");
|
||||||
|
|
||||||
// Expect user balance to decrease
|
// Expect user balance to decrease
|
||||||
|
@ -119,7 +119,7 @@ contract("Wormhole", function () {
|
||||||
assert.isTrue(threw);
|
assert.isTrue(threw);
|
||||||
|
|
||||||
// Lock assets
|
// Lock assets
|
||||||
let ev = await bridge.lockAssets(token.address, "1000000000000000000", "0x1230000000000000000000000000000000000000000000000000000000000000", 3 ,3);
|
let ev = await bridge.lockAssets(token.address, "1000000000000000000", "0x1230000000000000000000000000000000000000000000000000000000000000", 3, 3, false);
|
||||||
|
|
||||||
// Check that the lock event was emitted correctly
|
// Check that the lock event was emitted correctly
|
||||||
assert.lengthOf(ev.logs, 1)
|
assert.lengthOf(ev.logs, 1)
|
||||||
|
@ -129,7 +129,7 @@ contract("Wormhole", function () {
|
||||||
assert.equal(ev.logs[0].args.token, "0x000000000000000000000000d833215cbcc3f914bd1c9ece3ee7bf8b14f841bb")
|
assert.equal(ev.logs[0].args.token, "0x000000000000000000000000d833215cbcc3f914bd1c9ece3ee7bf8b14f841bb")
|
||||||
assert.equal(ev.logs[0].args.sender, "0x00000000000000000000000090f8bf6a479f320ead074411a4b0e7944ea8c9c1")
|
assert.equal(ev.logs[0].args.sender, "0x00000000000000000000000090f8bf6a479f320ead074411a4b0e7944ea8c9c1")
|
||||||
assert.equal(ev.logs[0].args.recipient, "0x1230000000000000000000000000000000000000000000000000000000000000")
|
assert.equal(ev.logs[0].args.recipient, "0x1230000000000000000000000000000000000000000000000000000000000000")
|
||||||
assert.equal(ev.logs[0].args.amount, "1000000000000000000")
|
assert.equal(ev.logs[0].args.amount, "1000000000")
|
||||||
|
|
||||||
// Check that the tokens were transferred to the bridge
|
// Check that the tokens were transferred to the bridge
|
||||||
assert.equal(await token.balanceOf("0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1"), "0");
|
assert.equal(await token.balanceOf("0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1"), "0");
|
||||||
|
@ -223,4 +223,67 @@ contract("Wormhole", function () {
|
||||||
// Test VAA signed by 5 signers (all except i=3)
|
// Test VAA signed by 5 signers (all except i=3)
|
||||||
await bridge.submitVAA("0x01000000020500e94bec8a17bd313522cdfea30cec5406a41a4cc4b6ec416a633ebe3aca070ae448e370e0a2e7c67fed04a2b825f56cf226c76e6ecd2e71865642393bf729dad80101ccf89506bef58d8cb12baabd60e3304cfb90ef0ef0657caba9c37ffa0d34a54c3aacd1a475ef4c72f24e8d9ce1e2de51e580ce85b18356436b6cda9e2ae9abc001033e9b4ff5fb545e964e907349e3dab0057c408c832bb31fb76fae7f81c3e488ea4897ce14db61c46d1169bd64b449498b1a18dee4de0ef2038b1c7e3a4a0239a0010432eac9532a4c0ce279d6a3018a5ea0d74402eb6969df5d444f20e0cca66d3b4c53e41cb18648f64af100c7410692e83fa16e5696b1f5f0d517653b003e22689800055859330bd1fee76d99728803fa26d739e494e1a232f5658150c2a2c97e1c9722793bdd83bd7cbb4a39b587b45093ee76187c72dfd68d64b7c0abc32bfef5d55c0000000fa010000000390102020105000000000000000000000000000000000000000000000000000000000000000000000000000000000090f8bf6a479f320ead074411a4b0e7944ea8c9c1010000000000000000000000000347ef34687bdc9f189e87a9200658d9c40e9988080000000000000000000000000000000000000000000000000de0b6b3a7640000")
|
await bridge.submitVAA("0x01000000020500e94bec8a17bd313522cdfea30cec5406a41a4cc4b6ec416a633ebe3aca070ae448e370e0a2e7c67fed04a2b825f56cf226c76e6ecd2e71865642393bf729dad80101ccf89506bef58d8cb12baabd60e3304cfb90ef0ef0657caba9c37ffa0d34a54c3aacd1a475ef4c72f24e8d9ce1e2de51e580ce85b18356436b6cda9e2ae9abc001033e9b4ff5fb545e964e907349e3dab0057c408c832bb31fb76fae7f81c3e488ea4897ce14db61c46d1169bd64b449498b1a18dee4de0ef2038b1c7e3a4a0239a0010432eac9532a4c0ce279d6a3018a5ea0d74402eb6969df5d444f20e0cca66d3b4c53e41cb18648f64af100c7410692e83fa16e5696b1f5f0d517653b003e22689800055859330bd1fee76d99728803fa26d739e494e1a232f5658150c2a2c97e1c9722793bdd83bd7cbb4a39b587b45093ee76187c72dfd68d64b7c0abc32bfef5d55c0000000fa010000000390102020105000000000000000000000000000000000000000000000000000000000000000000000000000000000090f8bf6a479f320ead074411a4b0e7944ea8c9c1010000000000000000000000000347ef34687bdc9f189e87a9200658d9c40e9988080000000000000000000000000000000000000000000000000de0b6b3a7640000")
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should correctly adjust decimals", async function () {
|
||||||
|
let bridge = await Wormhole.deployed();
|
||||||
|
let token = await ERC20.new("Test Token", "TKN");
|
||||||
|
|
||||||
|
await token.mint("0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1", "25000000000000000000000000000000000000");
|
||||||
|
|
||||||
|
// Approve bridge
|
||||||
|
await token.approve(bridge.address, "25000000000000000000000000000000000000");
|
||||||
|
|
||||||
|
// Lock assets
|
||||||
|
let ev = await bridge.lockAssets(token.address, "2000000000000000003", "0x1230000000000000000000000000000000000000000000000000000000000000", 3, 3, false);
|
||||||
|
|
||||||
|
// Check that the correct amount was logged
|
||||||
|
assert.lengthOf(ev.logs, 1)
|
||||||
|
assert.equal(ev.logs[0].event, "LogTokensLocked")
|
||||||
|
assert.equal(ev.logs[0].args.amount, "2000000000")
|
||||||
|
assert.equal(ev.logs[0].args.token_decimals, "9")
|
||||||
|
|
||||||
|
ev = await bridge.lockAssets(token.address, "2000000000000000000", "0x1230000000000000000000000000000000000000000000000000000000000000", 3, 3, false);
|
||||||
|
// Check that the correct amount was logged
|
||||||
|
assert.lengthOf(ev.logs, 1)
|
||||||
|
assert.equal(ev.logs[0].event, "LogTokensLocked")
|
||||||
|
assert.equal(ev.logs[0].args.amount, "2000000000")
|
||||||
|
|
||||||
|
await bridge.lockAssets(token.address, "18446744069709551615000000000", "0x1230000000000000000000000000000000000000000000000000000000000000", 3, 3, false);
|
||||||
|
let threw = false;
|
||||||
|
try {
|
||||||
|
await bridge.lockAssets(token.address, "1000000000", "0x1230000000000000000000000000000000000000000000000000000000000000", 3, 3, false);
|
||||||
|
} catch (e) {
|
||||||
|
threw = true;
|
||||||
|
assert.equal(e.reason, "bridge balance would exceed maximum")
|
||||||
|
}
|
||||||
|
assert.isTrue(threw, "accepted total bridge balance > MAX_U64")
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should refund dust", async function () {
|
||||||
|
let bridge = await Wormhole.deployed();
|
||||||
|
let token = await ERC20.new("Test Token", "TKN");
|
||||||
|
|
||||||
|
await token.mint("0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1", "5000000100");
|
||||||
|
|
||||||
|
// Approve bridge
|
||||||
|
await token.approve(bridge.address, "5000000100");
|
||||||
|
|
||||||
|
// Lock assets
|
||||||
|
let ev = await bridge.lockAssets(token.address, "1000000005", "0x1230000000000000000000000000000000000000000000000000000000000000", 3, 3, false);
|
||||||
|
|
||||||
|
// Check that dust was not subtracted
|
||||||
|
assert.lengthOf(ev.logs, 1)
|
||||||
|
assert.equal(ev.logs[0].event, "LogTokensLocked")
|
||||||
|
assert.equal(ev.logs[0].args.amount, "1")
|
||||||
|
assert.equal(await token.balanceOf("0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1"), "4000000095");
|
||||||
|
|
||||||
|
// Lock assets
|
||||||
|
ev = await bridge.lockAssets(token.address, "1000000005", "0x1230000000000000000000000000000000000000000000000000000000000000", 3, 3, true);
|
||||||
|
|
||||||
|
// Check that dust was refunded
|
||||||
|
assert.lengthOf(ev.logs, 1)
|
||||||
|
assert.equal(ev.logs[0].event, "LogTokensLocked")
|
||||||
|
assert.equal(ev.logs[0].args.amount, "1")
|
||||||
|
assert.equal((await token.balanceOf("0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1")).toString(), "3000000095");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue