Token-0x

First Flight #54
Beginner FriendlyDeFi
100 EXP
Submission Details
Impact: high
Likelihood: high

Unsafe Assembly Memory Access

Author Revealed upon completion

Summary

There are some assembly blocks that write to memory words in the ranges 0x40–0x5f and 0x60–0x7f, which can lead to undefined behavior.

Description

Memory structure:

  • 0x0 - 0x1f: first scratch word

  • 0x20 - 0x3f: second scratch word

  • 0x40 - 0x5f: free pointer

  • 0x60 - 0x7f: zero

  • >= 0x80: actual memory data

As the Solidity documentation notes, the free memory pointer and the zero slot are reserved and should not be used as scratch memory:

  • Memory allocated by yourself using a mechanism like the allocate function described above.

  • Memory allocated by Solidity, e.g. memory within the bounds of a memory array you reference.

  • The scratch space between memory offset 0 and 64 mentioned above.

  • Temporary memory that is located after the value of the free memory pointer at the beginning of the assembly block, i.e. memory that is “allocated” at the free memory pointer without updating the free memory pointer.

Two assembly blocks write to these unsafe memory locations:

function _transfer(...) {
//...
if lt(fromAmount, value) {
mstore(0x00, shl(224, 0xe450d38c))
mstore(add(0x00, 4), from)
mstore(add(0x00, 0x24), fromAmount)
mstore(add(0x00, 0x44), value)
revert(0x00, 0x64)
}
//...
}
function _spendAllowance(...) {
//...
if lt(currentAllowance, value) {
mstore(0x00, shl(224, 0xfb8f41b2))
mstore(add(0x00, 4), spender)
mstore(add(0x00, 0x24), currentAllowance)
mstore(add(0x00, 0x44), value)
revert(0, 0x64)
}
//...
}

As the Solidity documentation warns: "this will lead to incorrect and undefined behavior that cannot easily be discovered by testing."

Recommended Mitigation

Use safe memory ranges (e.g., memory addresses beyond the current free memory pointer) and avoid writing directly to 0x00 or other reserved regions.

//0x0 -> ptr
function _transfer(...) {
//...
if lt(fromAmount, value) {
mstore(ptr, shl(224, 0xe450d38c))
mstore(add(ptr, 4), from)
mstore(add(ptr, 0x24), fromAmount)
mstore(add(ptr, 0x44), value)
revert(ptr, 0x64)
}
//...
}
function _spendAllowance(...) {
//...
if lt(currentAllowance, value) {
mstore(ptr, shl(224, 0xfb8f41b2))
mstore(add(ptr, 4), spender)
mstore(add(ptr, 0x24), currentAllowance)
mstore(add(ptr, 0x44), value)
revert(ptr, 0x64)
}
//...
}

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.

Give us feedback!