Description
Component
Anvil
Have you ensured that all of these are up to date?
- Foundry
- Foundryup
What version of Foundry are you on?
forge Version: 1.1.0-nightly
What version of Foundryup are you on?
no output
What command(s) is the bug in?
No response
Operating System
macOS (Intel)
Describe the bug
I created a small repo for the code: https://github.com/0xwetzo/Anvil-Celo
The justfile
helps to run the code step by step and make changes.
The issue seems to be with balance updates for native tokens like CELO or METIS that are both gas token and ERC20 at the same time.
The balances are not properly updating during the transaction, as seen in the traces, and are incorrect at the end of it too, using cast balance
.
The function receives native CELO and calls a mock swap router that will swap ERC20 CELO for USDC, then sends remaining balance to caller as ERC20.
function test(address router, bytes calldata data) external payable {
uint256 balance = address(this).balance;
NATIVE_TOKEN.approve(router, balance);
(bool success, ) = router.call(data);
require(success);
uint256 newBalance = NATIVE_TOKEN.balanceOf(address(this));
NATIVE_TOKEN.transfer(msg.sender, newBalance);
}
The expected and observed balances are:
# Expected balances (CELO) Init Test called Router called Final transfer
# Owner 10,000 9,999 9,999 9.999.5
# Contract 0 1 0.5 0
# Router 0 0 0.5 0.5
# Trace balances Init Test called Router called Final transfer
# Owner >= 1 >= 0 >= 0 >= 0.5
# Contract 0 1 1 (wrong) 0
# Router 0 0 0.5 0.5
# Cast balances Init Test called Router called Final transfer
# Owner 10,000 ? ? 9,999
# Contract 0 ? ? 1 (wrong)
# Router 0 ? ? 0 (wrong)
And the traces:
Traces:
[97908] 0x8198f5d8F8CfFE8f9C413d98a0A55aEB8ab9FbB7::test{value: 1000000000000000000}(0x0355B7B8cb128fA5692729Ab3AAa199C1753f726, 0xfe029156000000000000000000000000471ece3750da237f93b8e339c536989b8978a438000000000000000000000000ceba9300f2b948710d2653dd7b07f33a8b32118c00000000000000000000000000000000000000000000000006f05b59d3b2000000000000000000000000000000000000000000000000000000000000075bcd15)
├─ [29958] 0x471EcE3750Da237f93B8E339c536989b8978a438::approve(0x0355B7B8cb128fA5692729Ab3AAa199C1753f726, 1000000000000000000 [1e18])
│ ├─ [24552] 0xFa77529cD8F0dD86df93CC0d53ed9Bb5Db0ad6D5::approve(0x0355B7B8cb128fA5692729Ab3AAa199C1753f726, 1000000000000000000 [1e18]) [delegatecall]
│ │ ├─ emit Approval(param0: 0x8198f5d8F8CfFE8f9C413d98a0A55aEB8ab9FbB7, param1: 0x0355B7B8cb128fA5692729Ab3AAa199C1753f726, param2: 1000000000000000000 [1e18])
│ │ └─ ← [Return] 0x0000000000000000000000000000000000000000000000000000000000000001
│ └─ ← [Return] 0x0000000000000000000000000000000000000000000000000000000000000001
├─ [53790] 0x0355B7B8cb128fA5692729Ab3AAa199C1753f726::swap(0x471EcE3750Da237f93B8E339c536989b8978a438, 0xcebA9300f2b948710d2653dD7B07f33A8B32118C, 500000000000000000 [5e17], 123456789 [1.234e8])
│ ├─ [7907] 0x471EcE3750Da237f93B8E339c536989b8978a438::transferFrom(0x8198f5d8F8CfFE8f9C413d98a0A55aEB8ab9FbB7, 0x0355B7B8cb128fA5692729Ab3AAa199C1753f726, 500000000000000000 [5e17])
│ │ ├─ [6995] 0xFa77529cD8F0dD86df93CC0d53ed9Bb5Db0ad6D5::transferFrom(0x8198f5d8F8CfFE8f9C413d98a0A55aEB8ab9FbB7, 0x0355B7B8cb128fA5692729Ab3AAa199C1753f726, 500000000000000000 [5e17]) [delegatecall]
│ │ │ ├─ [0] 0x00000000000000000000000000000000000000fd::00000000(00000000000000008198f5d8f8cffe8f9c413d98a0a55aeb8ab9fbb70000000000000000000000000355b7b8cb128fa5692729ab3aaa199c1753f72600000000000000000000000000000000000000000000000006f05b59d3b20000)
│ │ │ │ └─ ← [Stop]
│ │ │ ├─ emit Transfer(param0: 0x8198f5d8F8CfFE8f9C413d98a0A55aEB8ab9FbB7, param1: 0x0355B7B8cb128fA5692729Ab3AAa199C1753f726, param2: 500000000000000000 [5e17])
│ │ │ └─ ← [Return] 0x0000000000000000000000000000000000000000000000000000000000000001
│ │ └─ ← [Return] 0x0000000000000000000000000000000000000000000000000000000000000001
│ ├─ [40563] 0xcebA9300f2b948710d2653dD7B07f33A8B32118C::transfer(0x8198f5d8F8CfFE8f9C413d98a0A55aEB8ab9FbB7, 123456789 [1.234e8])
│ │ ├─ [33363] 0xdA06D4e3F59fE2C8ff3077A9D50D5BE5E231BEcD::transfer(0x8198f5d8F8CfFE8f9C413d98a0A55aEB8ab9FbB7, 123456789 [1.234e8]) [delegatecall]
│ │ │ ├─ emit Transfer(param0: 0x0355B7B8cb128fA5692729Ab3AAa199C1753f726, param1: 0x8198f5d8F8CfFE8f9C413d98a0A55aEB8ab9FbB7, param2: 123456789 [1.234e8])
│ │ │ └─ ← [Return] 0x0000000000000000000000000000000000000000000000000000000000000001
│ │ └─ ← [Return] 0x0000000000000000000000000000000000000000000000000000000000000001
│ └─ ← [Stop]
├─ [1423] 0x471EcE3750Da237f93B8E339c536989b8978a438::balanceOf(0x8198f5d8F8CfFE8f9C413d98a0A55aEB8ab9FbB7) [staticcall]
│ ├─ [523] 0xFa77529cD8F0dD86df93CC0d53ed9Bb5Db0ad6D5::balanceOf(0x8198f5d8F8CfFE8f9C413d98a0A55aEB8ab9FbB7) [delegatecall]
│ │ └─ ← [Return] 0x0000000000000000000000000000000000000000000000000de0b6b3a7640000
│ └─ ← [Return] 0x0000000000000000000000000000000000000000000000000de0b6b3a7640000
├─ [4299] 0x471EcE3750Da237f93B8E339c536989b8978a438::transfer(0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266, 1000000000000000000 [1e18])
│ ├─ [3393] 0xFa77529cD8F0dD86df93CC0d53ed9Bb5Db0ad6D5::transfer(0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266, 1000000000000000000 [1e18]) [delegatecall]
│ │ ├─ [0] 0x00000000000000000000000000000000000000fd::00000000(00000000000000008198f5d8f8cffe8f9c413d98a0a55aeb8ab9fbb7000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb922660000000000000000000000000000000000000000000000000de0b6b3a7640000)
│ │ │ └─ ← [Stop]
│ │ ├─ emit Transfer(param0: 0x8198f5d8F8CfFE8f9C413d98a0A55aEB8ab9FbB7, param1: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266, param2: 1000000000000000000 [1e18])
│ │ └─ ← [Return] 0x0000000000000000000000000000000000000000000000000000000000000001
│ └─ ← [Return] 0x0000000000000000000000000000000000000000000000000000000000000001
└─ ← [Stop]
Transaction successfully executed.
I presume that the bug comes from Anvil and the special management of the hybrid token CELO.
Metadata
Metadata
Assignees
Type
Projects
Status