forge-std icon indicating copy to clipboard operation
forge-std copied to clipboard

`deal` does not work on Aave's aTokens or other tokens that perform computation in `balanceOf`

Open sourabhmarathe opened this issue 3 years ago • 4 comments

Component

forge-std

Have you ensured that all of these are up to date?

  • [X] Foundry
  • [X] Foundryup

What version of Foundry are you on?

forge 0.2.0 (4b720c2 2022-07-28T00:04:25.986568Z)

What command(s) is the bug in?

forge test

Operating System

macOS (Intel)

Describe the bug

I have not been able to call deal on Aave's aToken (address: 0xBcca60bB61934080951369a648Fb03DF4F96263C). I have shared the stacktrace for the deal call below.

This happens in a test where the first line of the function is deal(token, msg.sender, amount);. The error message is [FAIL. Reason: stdStorage find(StdStorage): Slot(s) not found.].

In addition, it appears that aTokens are ERC20 compliant (their website states that aTokens support basic EIP20 functions).

Stack trace:

    ├─ [23586] InitializableImmutableAdminUpgradeabilityProxy::balanceOf(0x00a329c0648769a73afac7f9381e08fb43dbea72) 
    │   ├─ [18475] AToken::balanceOf(0x00a329c0648769a73afac7f9381e08fb43dbea72) [delegatecall]
    │   │   ├─ [12856] InitializableImmutableAdminUpgradeabilityProxy::getReserveNormalizedIncome(0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48) [staticcall]
    │   │   │   ├─ [7745] LendingPool::getReserveNormalizedIncome(0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48) [delegatecall]
    │   │   │   │   └─ ← 1076877460561699683403779143
    │   │   │   └─ ← 1076877460561699683403779143
    │   │   └─ ← 0
    │   └─ ← 0
    ├─ [0] VM::record() 
    │   └─ ← ()
    ├─ [4086] InitializableImmutableAdminUpgradeabilityProxy::balanceOf(0x00a329c0648769a73afac7f9381e08fb43dbea72) [staticcall]
    │   ├─ [3475] AToken::balanceOf(0x00a329c0648769a73afac7f9381e08fb43dbea72) [delegatecall]
    │   │   ├─ [2356] InitializableImmutableAdminUpgradeabilityProxy::getReserveNormalizedIncome(0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48) [staticcall]
    │   │   │   ├─ [1745] LendingPool::getReserveNormalizedIncome(0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48) [delegatecall]
    │   │   │   │   └─ ← 1076877460561699683403779143
    │   │   │   └─ ← 1076877460561699683403779143
    │   │   └─ ← 0
    │   └─ ← 0
    ├─ [0] VM::accesses(InitializableImmutableAdminUpgradeabilityProxy: [0xbcca60bb61934080951369a648fb03df4f96263c]) 
    │   └─ ← [0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc, 0x7db14a3e80dc3d3973ac59ab9dd6e51be0941d8302f988ebabbd9d9f72c15b36], []
    ├─ [0] VM::load(InitializableImmutableAdminUpgradeabilityProxy: [0xbcca60bb61934080951369a648fb03df4f96263c], 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc) 
    │   └─ ← 0x0000000000000000000000001c050bca8babe53ef769d0d2e411f556e1a27e7b
    ├─ [0] VM::store(InitializableImmutableAdminUpgradeabilityProxy: [0xbcca60bb61934080951369a648fb03df4f96263c], 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc, 0x1337000000000000000000000000000000000000000000000000000000000000) 
    │   └─ ← ()
    ├─ [3108] InitializableImmutableAdminUpgradeabilityProxy::balanceOf(0x00a329c0648769a73afac7f9381e08fb43dbea72) [staticcall]
    │   ├─ [0] 0x0000…0000::balanceOf(0x00a329c0648769a73afac7f9381e08fb43dbea72) [delegatecall]
    │   │   └─ ← ()
    │   └─ ← ()
    ├─ [0] VM::store(InitializableImmutableAdminUpgradeabilityProxy: [0xbcca60bb61934080951369a648fb03df4f96263c], 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc, 0x0000000000000000000000001c050bca8babe53ef769d0d2e411f556e1a27e7b) 
    │   └─ ← ()
    ├─ [0] VM::load(InitializableImmutableAdminUpgradeabilityProxy: [0xbcca60bb61934080951369a648fb03df4f96263c], 0x7db14a3e80dc3d3973ac59ab9dd6e51be0941d8302f988ebabbd9d9f72c15b36) 
    │   └─ ← 0x0000000000000000000000000000000000000000000000000000000000000000
    ├─ emit WARNING_UninitedSlot(who: InitializableImmutableAdminUpgradeabilityProxy: [0xbcca60bb61934080951369a648fb03df4f96263c], slot: 56852350417691002906141485739722008029934276939945103568888814915257509174070)
    ├─ [0] VM::store(InitializableImmutableAdminUpgradeabilityProxy: [0xbcca60bb61934080951369a648fb03df4f96263c], 0x7db14a3e80dc3d3973ac59ab9dd6e51be0941d8302f988ebabbd9d9f72c15b36, 0x1337000000000000000000000000000000000000000000000000000000000000) 
    │   └─ ← ()
    ├─ [4535] InitializableImmutableAdminUpgradeabilityProxy::balanceOf(0x00a329c0648769a73afac7f9381e08fb43dbea72) [staticcall]
    │   ├─ [3911] AToken::balanceOf(0x00a329c0648769a73afac7f9381e08fb43dbea72) [delegatecall]
    │   │   ├─ [2356] InitializableImmutableAdminUpgradeabilityProxy::getReserveNormalizedIncome(0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48) [staticcall]
    │   │   │   ├─ [1745] LendingPool::getReserveNormalizedIncome(0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48) [delegatecall]
    │   │   │   │   └─ ← 1076877460561699683403779143
    │   │   │   └─ ← 1076877460561699683403779143
    │   │   └─ ← "48"
    │   └─ ← "48"
    ├─ [0] VM::store(InitializableImmutableAdminUpgradeabilityProxy: [0xbcca60bb61934080951369a648fb03df4f96263c], 0x7db14a3e80dc3d3973ac59ab9dd6e51be0941d8302f988ebabbd9d9f72c15b36, 0x0000000000000000000000000000000000000000000000000000000000000000) 
    │   └─ ← ()
    └─ ← "stdStorage find(StdStorage): Slot(s) not found."

sourabhmarathe avatar Jul 28 '22 16:07 sourabhmarathe

it's because they do math on the stored value and it returns an overflow error. We should change the default value for deal to 1337 instead of 0x13370000..000, and that should fix it.

image

brockelmore avatar Aug 03 '22 04:08 brockelmore

Tried looking into this actually. Changing it from bytes32(hex"1337") to bytes32(uint256(1337)) will get it further in the code but it will still fail on this check. Also tried it against your storage PR where it failed at the same spot. Will continue looking into stdStorage but thought I'd make you aware.

Sabnock01 avatar Aug 18 '22 05:08 Sabnock01

Not sure if this will help anyone, but to shed some light on this: While the aToken follows erc20 it's implemented slightly different internally - balances is a mapping of struct, so not uint256, but (uint128,uint128), where first is balance, second it index.

To deal someone e.g. x aDAI there's infinite possibilities to represent this with the struct, by choosing index + balance wisely in relation to the current index. Probably the most reasonable way would be to:

  • fetch the current index i from the attached pool
  • scale x down by i as y and write storage as y,i

Checked the code a bit though, and not sure how reasonable it would be to have such a special case for aTokens :sweat_smile:

sakulstra avatar Feb 20 '23 21:02 sakulstra

Also using this issue to track other tokens this has been reported for:

  • OUSD: https://github.com/foundry-rs/foundry/issues/4595
  • DIGG: https://github.com/foundry-rs/forge-std/issues/444

mds1 avatar Aug 29 '23 13:08 mds1