Skip to content

Commit

Permalink
Merge pull request #21 from ProjectOpenSea/0age-patch-1
Browse files Browse the repository at this point in the history
Make ERC20 preapproval check branchless
  • Loading branch information
0age authored Nov 29, 2023
2 parents 38aad7a + e321e65 commit 057bb1f
Show file tree
Hide file tree
Showing 2 changed files with 9 additions and 10 deletions.
1 change: 1 addition & 0 deletions .git-blame-ignore-revs
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
# Github Actions automatically updated formatting with forge fmt\n3b40d0f5cfd25b67a335ee2c8d7c9660d5bfd7f5
# Github Actions automatically updated formatting with forge fmt\n2d96311b29055c5b9a0b632176ce3b8d78a23a89
# Github Actions automatically updated formatting with forge fmt\ne2d336bbb0331c7716c16fed64f51be6c270ad02
# Github Actions automatically updated formatting with forge fmt\n3458423c8716bdcd3875cde4597dcae377a16620
18 changes: 8 additions & 10 deletions src/tokens/erc20/ERC20ConduitPreapproved_Solady.sol
Original file line number Diff line number Diff line change
Expand Up @@ -61,16 +61,13 @@ abstract contract ERC20ConduitPreapproved_Solady is ERC20, IPreapprovalForAll {
mstore(0x0c, or(from_, SOLADY_ERC20_ALLOWANCE_SLOT_SEED))
let allowanceSlot := keccak256(0x0c, 0x34)
let allowance_ := sload(allowanceSlot)
// If the caller is the conduit and allowance is 0, set to type(uint256).max. If the allowance is type(uint256).max, set to 0.
let isConduit := eq(caller(), CONDUIT)
if isConduit {
let conduitAllowance_ := allowance_
if eq(allowance_, 0) { conduitAllowance_ := not(0) }
if eq(allowance_, not(0)) { conduitAllowance_ := 0 }
if iszero(eq(allowance_, conduitAllowance_)) { allowance_ := conduitAllowance_ }
}
// If the allowance is not the maximum uint256 value.
if add(allowance_, 1) {

// "flip" allowance if caller is CONDUIT and if allowance_ is 0 or type(uint256).max.
allowance_ :=
xor(allowance_, mul(and(eq(caller(), CONDUIT), iszero(and(allowance_, not(allowance_)))), not(0)))

// If the allowance is not the maximum uint256 value:
if not(allowance_) {
// Revert if the amount to be transferred exceeds the allowance.
if gt(amount, allowance_) {
mstore(0x00, 0x13be252b) // `InsufficientAllowance()`.
Expand All @@ -79,6 +76,7 @@ abstract contract ERC20ConduitPreapproved_Solady is ERC20, IPreapprovalForAll {
// Subtract and store the updated allowance.
sstore(allowanceSlot, sub(allowance_, amount))
}

// Compute the balance slot and load its value.
mstore(0x0c, or(from_, SOLADY_ERC20_BALANCE_SLOT_SEED))
let fromBalanceSlot := keccak256(0x0c, 0x20)
Expand Down

0 comments on commit 057bb1f

Please sign in to comment.