diff --git a/cpp/contracts/adapter.cpp b/cpp/contracts/adapter.cpp index 3f0c46f7..52cd9b7e 100644 --- a/cpp/contracts/adapter.cpp +++ b/cpp/contracts/adapter.cpp @@ -53,7 +53,7 @@ void adapter::create( check(is_account(token), "token account does not exist"); } - symbol non_local_token_symbol = symbol(symbol_code("XXX"), 0); + symbol non_local_token_symbol = symbol(symbol_code("XXX"), token_symbol.precision()); adapter_registry_table registry_data { .token = token, @@ -187,9 +187,7 @@ void adapter::settle(const name& caller, const operation& operation, const metad registry_adapter _registry(get_self(), get_self().value); check(_registry.exists(), "contract not inizialized"); adapter_registry_table registry_data = _registry.get(); - check (registry_data.token_bytes == operation.token, "underlying token does not match with adapter registry"); - check(registry_data.xerc20_symbol == operation.amount.symbol, "registered xerc20 symbols differs from the operation one"); // TODO: test me - + check(registry_data.token_bytes == operation.token, "underlying token does not match with adapter registry"); checksum256 event_id; // output pam::check_authorization(get_self(), operation, metadata, event_id); @@ -212,9 +210,9 @@ void adapter::settle(const name& caller, const operation& operation, const metad name xerc20 = registry_data.xerc20; check(is_account(xerc20), "Not valid xerc20 name"); - if (operation.amount.amount > 0) { - asset quantity(operation.amount.amount, registry_data.xerc20_symbol); - + if (operation.amount > 0) { + asset adj_operation_amount = adjust_precision(operation.amount, registry_data.token_symbol, registry_data.xerc20_symbol); + asset quantity(adj_operation_amount.amount, registry_data.xerc20_symbol); lockbox_singleton _lockbox(xerc20, xerc20.value); action_mint _mint(registry_data.xerc20, {get_self(), "active"_n}); if (_lockbox.exists()) { diff --git a/cpp/contracts/operation.hpp b/cpp/contracts/operation.hpp index 0b256433..cbe8bb26 100644 --- a/cpp/contracts/operation.hpp +++ b/cpp/contracts/operation.hpp @@ -14,7 +14,7 @@ namespace eosio { checksum256 token; // erc20 on EVM bytes originChainId; bytes destinationChainId; - asset amount; + uint128_t amount; bytes sender; name recipient; bytes data; diff --git a/cpp/contracts/pam.hpp b/cpp/contracts/pam.hpp index 156d1820..67f202dc 100644 --- a/cpp/contracts/pam.hpp +++ b/cpp/contracts/pam.hpp @@ -148,7 +148,7 @@ namespace eosio { bytes amount = extract_32bytes(event_data, offset); uint128_t amount_num = bytes32_to_uint128(amount); - check(to_wei(operation.amount) == amount_num, "amount do not match"); + check(operation.amount == amount_num, "amount do not match"); offset += 32; bytes sender = extract_32bytes(event_data, offset); diff --git a/cpp/contracts/tables/adapter_registry.table.hpp b/cpp/contracts/tables/adapter_registry.table.hpp index 45d02048..394b8675 100644 --- a/cpp/contracts/tables/adapter_registry.table.hpp +++ b/cpp/contracts/tables/adapter_registry.table.hpp @@ -23,8 +23,9 @@ namespace eosio { // WETH ERC20 => local chain is Ethereum, then adapter's registry is // // |_____token____|___token_symbol___|______token_bytes_______|_____xerc20_____| - // | '' | '0,XXX' | bytes32(address(WETH)) | 'xweth.token' | - // NOTE: for not local token_symbol = '0,XXX' + // | '' | '18,XXX' | bytes32(address(WETH)) | 'xweth.token' | + // + // NOTE: for not local token_symbol = ',XXX' TABLE adapter_registry_table { name token; diff --git a/cpp/contracts/utils.hpp b/cpp/contracts/utils.hpp index 1330ff94..872d7bf2 100644 --- a/cpp/contracts/utils.hpp +++ b/cpp/contracts/utils.hpp @@ -131,6 +131,22 @@ namespace eosio { return asset(amount / powint(10, exp), sym); } + asset adjust_precision(uint128_t amount, const symbol& from_symbol, const symbol& to_symbol) { + int16_t exp = from_symbol.precision() - to_symbol.precision(); + uint128_t factor; + uint128_t adjusted_amount; + if (exp < 0) { + exp = -exp; + factor = powint(10, exp); + adjusted_amount = amount * factor; + } else { + print("WARNING: Operation precision exceeds destination symbol; amount will be floored to destination symbol precision."); + factor = powint(10, exp); + adjusted_amount = amount / factor; + } + return asset(adjusted_amount, to_symbol); + } + bytes extract_32bytes(const bytes& data, uint128_t offset) { bytes _data(data.begin() + offset, data.begin() + offset + 32); return _data; diff --git a/cpp/package.json b/cpp/package.json index 1e5a84e2..12f844bd 100644 --- a/cpp/package.json +++ b/cpp/package.json @@ -12,7 +12,7 @@ "test": "yarn build && mocha", "lint": "./lint scripts/*.sh && npx prettier --check test/", "prettier:fix": "npx prettier --check --write test/", - "prettier": "npx prettier --cache --check --ignore-path ../.prettierignore --config ../.prettierrc ./src ./test" + "prettier": "npx prettier --cache --check --ignore-path ../.prettierignore --config ../.prettierrc ./contracts ./test" }, "devDependencies": { "@eosnetwork/vert": "^1.0.0", diff --git a/cpp/test/adapter-non-local.test.js b/cpp/test/adapter-non-local.test.js index 8b99b3f4..23daaea0 100644 --- a/cpp/test/adapter-non-local.test.js +++ b/cpp/test/adapter-non-local.test.js @@ -22,7 +22,7 @@ const { evmAdapter, } = require('./samples/evm-operations') const { evmMetadataSamples, teePubKey } = require('./samples/evm-metadata') -const { adjustPrecision } = require('./utils/precision-utils') +const { adjustPrecision, fromWei } = require('./utils/precision-utils') const attestation = 'deadbeef' @@ -318,7 +318,7 @@ describe('Adapter EVM -> EOS testing', () => { expect(row).to.be.deep.equal({ token: '', - token_symbol: precision(0, 'XXX'), + token_symbol: precision(18, 'XXX'), token_bytes: evmUnderlyingToken.bytes, xerc20: evmXERC20.account, xerc20_symbol: precision(evmXERC20.precision, evmXERC20.symbol), @@ -517,6 +517,12 @@ describe('Adapter EVM -> EOS testing', () => { }) describe('adapter::settle', () => { + const createOperationAsset = amount => + Asset.from( + amount / 10 ** evmPrecision, + precision(evmXERC20.precision, evmXERC20.symbol), + ) + it('Should reject if adapter and token do not match', async () => { const operation = evmOperationSamples.pegin const metadata = evmMetadataSamples.pegin @@ -546,7 +552,10 @@ describe('Adapter EVM -> EOS testing', () => { [evmXERC20], ) - expect(after[recipient][evmXERC20.symbol]).to.be.equal(operation.amount) + const operationAsset = createOperationAsset(operation.amount) + expect(after[recipient][evmXERC20.symbol]).to.be.equal( + operationAsset.toString(), + ) expect(after[adapter.account][evmXERC20.symbol]).to.be.equal( `0.0000 ${evmXERC20.symbol}`, @@ -576,8 +585,45 @@ describe('Adapter EVM -> EOS testing', () => { [evmXERC20], ) + const operationAsset = createOperationAsset(operation.amount) + expect(after[recipient][evmXERC20.symbol]).to.equal( + sum(operationAsset, beforeAsset).toString(), + ) + + expect(after[adapter.account][evmXERC20.symbol]).to.be.equal( + `0.0000 ${evmXERC20.symbol}`, + ) + }) + + it('Should truncate the passed amount to the set precision', async () => { + const operation = evmOperationSamples.peginLargePrecision + const metadata = evmMetadataSamples.peginLargePrecision + + const before = getAccountsBalances( + [user, recipient, adapter.account], + [evmXERC20], + ) + const beforeAsset = Asset.from(before[recipient][evmXERC20.symbol]) + + await adapter.contract.actions + .settle([user, operation, metadata]) + .send(active(user)) + + console.log(adapter.contract.bc.console) + + const after = getAccountsBalances( + [user, recipient, adapter.account], + [evmXERC20], + ) + + const operationAsset = createOperationAsset(operation.amount) + const adjAmount = adjustPrecision( + operationAsset.toString(), + evmXERC20Precision, + ) + const adjOperationAmount = Asset.from(`${adjAmount} ${evmXERC20.symbol}`) expect(after[recipient][evmXERC20.symbol]).to.equal( - sum(operation.amount, beforeAsset).toString(), + sum(adjOperationAmount, beforeAsset).toString(), ) expect(after[adapter.account][evmXERC20.symbol]).to.be.equal( diff --git a/cpp/test/pam.test.js b/cpp/test/pam.test.js index 0c315163..bedfc9e7 100644 --- a/cpp/test/pam.test.js +++ b/cpp/test/pam.test.js @@ -59,7 +59,7 @@ describe('PAM testing', () => { const eosChainId = 'aca376f206b8fc25a6ed44dbdc66547c36c6c33e3a119ffbeaef943642f0e906' const operation = getOperationSample({ - amount: '1337.0000 TKN', + amount: '1337000000000000000000', sender: '0000000000000000000000002b5ad5c4795c026514f8317c7a215e218dccd6cf', token: '000000000000000000000000f2e246bb76df876cef8b38ae84130f4f55de395b', chainId: eosChainId, @@ -327,7 +327,7 @@ describe('PAM testing', () => { '0000000000000000000000000000000000000000000000746b6e2e746f6b656e' const originChainId = no0x(Chains(Protocols.Eos).Jungle) const destinationChainId = eosChainId - const amount = '9.9825 TKN' + const amount = '9982500000000000000' const sender = '0000000000000000000000000000000000000000000000000000000075736572' const recipient = 'recipient' diff --git a/cpp/test/samples/evm-metadata.js b/cpp/test/samples/evm-metadata.js index 70d2ae18..9955fdab 100644 --- a/cpp/test/samples/evm-metadata.js +++ b/cpp/test/samples/evm-metadata.js @@ -18,6 +18,12 @@ const evmMetadataSamples = { signature: '1b5d941f9856d83e6776500344e4e62bfe66deb509c509228bb2ab88d32b8a2dee290c160bf5c575034c88dd39d4b598f5fa7080a97be90398437cb3ccb9049051', }, + peginLargePrecision: { + preimage: + '010100000000000000000000000000000000000000000000000000000000000000019c6d1358f426fe23fc7cf0e67aa422ff27c4e5ec7899297a10f036e6cf6643da96d4d6885f072cb3f734d1b4add1d78d46487692cf9d912a6a91cfc6c65bc7d6000000000000000000000000bcf063a9eb18bc3c6eb005791c61801b7cb16fe466756e6473206172652073616675207361667520736166752073616675202e2e0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000810090f35dfa6b18b5eb59d298e2a2443a2811e2aca376f206b8fc25a6ed44dbdc66547c36c6c33e3a119ffbeaef943642f0e9060000000000000000000000000000000000000000000000001080f0f245c7e965000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266000000000000000000000000000000000000000000000000000000000000000c656f73726563697069656e74', + signature: + '1c788142219de023a33e6916e3f396084003401be5551e5f972d9e628cf9685ab740a4619cd30e2adfd21527f50835f3b993ef19d398592c55bd362eec6ddb7cd9', + }, peginWithWrongSignature: { preimage: '010100000000000000000000000000000000000000000000000000000000000000017e21ba208ea2a072bad2d011dbc3a9f870c574a66203d84bde926fcf85756d782e3704b180feda25af9dfe50793e292fd99d644aa505c3d170fa69407091dbd3000000000000000000000000bcf063a9eb18bc3c6eb005791c61801b7cb16fe466756e6473206172652073616675207361667520736166752073616675202e2e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000810090f35dfa6b18b5eb59d298e2a2443a2811e2aca376f206b8fc25a6ed44dbdc66547c36c6c33e3a119ffbeaef943642f0e906000000000000000000000000000000000000000000000000517d3388612e7c00000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266000000000000000000000000000000000000000000000000000000000000000c656f73726563697069656e74', diff --git a/cpp/test/samples/evm-operations.js b/cpp/test/samples/evm-operations.js index 84d4c4e1..99036cd7 100644 --- a/cpp/test/samples/evm-operations.js +++ b/cpp/test/samples/evm-operations.js @@ -16,7 +16,7 @@ const evmOperationSamples = { '0000000000000000000000000000000000000000000000000000000000000001', // EVM mainnet chain id destinationChainId: 'aca376f206b8fc25a6ed44dbdc66547c36c6c33e3a119ffbeaef943642f0e906', // EOS chain id - amount: '5.87190615 XTST', + amount: '5871906150000000000', sender: '000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266', recipient: 'eosrecipient', data: '', @@ -30,11 +30,25 @@ const evmOperationSamples = { '0000000000000000000000000000000000000000000000000000000000000001', // ETH chain id destinationChainId: 'aca376f206b8fc25a6ed44dbdc66547c36c6c33e3a119ffbeaef943642f0e906', // EOS chain id - amount: '0.99749956 XTST', + amount: '997499560000000000', sender: '000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266', recipient: 'eosrecipient', data: '12345abcdefc0de1337f', }, + peginLargePrecision: { + blockId: '9c6d1358f426fe23fc7cf0e67aa422ff27c4e5ec7899297a10f036e6cf6643da', + txId: '96d4d6885f072cb3f734d1b4add1d78d46487692cf9d912a6a91cfc6c65bc7d6', + nonce: 0, + token: '000000000000000000000000810090f35dfa6b18b5eb59d298e2a2443a2811e2', + originChainId: + '0000000000000000000000000000000000000000000000000000000000000001', // ETH chain id + destinationChainId: + 'aca376f206b8fc25a6ed44dbdc66547c36c6c33e3a119ffbeaef943642f0e906', // EOS chain id + amount: '1189215224969292133', + sender: '000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266', + recipient: 'eosrecipient', + data: '', + }, } module.exports = { diff --git a/cpp/test/utils/get-operation-sample.js b/cpp/test/utils/get-operation-sample.js index a135ce59..05fc0f5e 100644 --- a/cpp/test/utils/get-operation-sample.js +++ b/cpp/test/utils/get-operation-sample.js @@ -13,7 +13,7 @@ const getOperationSample = _injectedOperation => '0000000000000000000000000000000000000000000000000000000000000001', // ETH chain id destinationChainId: 'aca376f206b8fc25a6ed44dbdc66547c36c6c33e3a119ffbeaef943642f0e906', // EOS chain id - amount: '5.889675 XTKN', + amount: '5889675000000000000', sender: '0x000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266', recipient: 'destinatieos',