Skip to content

Commit

Permalink
Fix ERC721_safeMint onERC721Received check (OpenZeppelin#174)
Browse files Browse the repository at this point in the history
  • Loading branch information
0xChqrles authored Jan 31, 2022
1 parent f8f0d98 commit 88038a7
Showing 1 changed file with 66 additions and 64 deletions.
130 changes: 66 additions & 64 deletions contracts/token/ERC721_base.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ end
#

func ERC721_initializer{
syscall_ptr : felt*,
syscall_ptr : felt*,
pedersen_ptr : HashBuiltin*,
range_check_ptr
}(
Expand Down Expand Up @@ -95,7 +95,7 @@ func ERC721_symbol{
end

func ERC721_balanceOf{
syscall_ptr : felt*,
syscall_ptr : felt*,
pedersen_ptr : HashBuiltin*,
range_check_ptr
}(owner: felt) -> (balance: Uint256):
Expand All @@ -105,8 +105,8 @@ func ERC721_balanceOf{
end

func ERC721_ownerOf{
syscall_ptr: felt*,
pedersen_ptr: HashBuiltin*,
syscall_ptr: felt*,
pedersen_ptr: HashBuiltin*,
range_check_ptr
}(token_id: Uint256) -> (owner: felt):
uint256_check(token_id)
Expand All @@ -117,8 +117,8 @@ func ERC721_ownerOf{
end

func ERC721_getApproved{
syscall_ptr: felt*,
pedersen_ptr: HashBuiltin*,
syscall_ptr: felt*,
pedersen_ptr: HashBuiltin*,
range_check_ptr
}(token_id: Uint256) -> (approved: felt):
uint256_check(token_id)
Expand All @@ -130,17 +130,17 @@ func ERC721_getApproved{
end

func ERC721_isApprovedForAll{
syscall_ptr: felt*,
pedersen_ptr: HashBuiltin*,
syscall_ptr: felt*,
pedersen_ptr: HashBuiltin*,
range_check_ptr
}(owner: felt, operator: felt) -> (is_approved: felt):
let (is_approved) = ERC721_operator_approvals.read(owner=owner, operator=operator)
return (is_approved)
end

func ERC721_tokenURI{
syscall_ptr: felt*,
pedersen_ptr: HashBuiltin*,
syscall_ptr: felt*,
pedersen_ptr: HashBuiltin*,
range_check_ptr
}(token_id: Uint256) -> (token_uri: felt):
let (exists) = _exists(token_id)
Expand All @@ -156,8 +156,8 @@ end
#

func ERC721_approve{
pedersen_ptr: HashBuiltin*,
syscall_ptr: felt*,
pedersen_ptr: HashBuiltin*,
syscall_ptr: felt*,
range_check_ptr
}(to: felt, token_id: Uint256):
uint256_check(token_id)
Expand All @@ -183,18 +183,18 @@ func ERC721_approve{
end

func ERC721_setApprovalForAll{
syscall_ptr: felt*,
pedersen_ptr: HashBuiltin*,
syscall_ptr: felt*,
pedersen_ptr: HashBuiltin*,
range_check_ptr
}(operator: felt, approved: felt):
# Ensures caller is neither zero address nor operator
let (caller) = get_caller_address()
assert_not_zero(caller * operator)
# note this pattern as we'll frequently use it:
assert_not_zero(caller * operator)
# note this pattern as we'll frequently use it:
# instead of making an `assert_not_zero` call for each address
# we can always briefly write `assert_not_zero(a0 * a1 * ... * aN)`.
# This is because these addresses are field elements,
# meaning that a*0==0 for all a in the field,
# meaning that a*0==0 for all a in the field,
# and a*b==0 implies that at least one of a,b are zero in the field
assert_not_equal(caller, operator)

Expand All @@ -206,8 +206,8 @@ func ERC721_setApprovalForAll{
end

func ERC721_transferFrom{
pedersen_ptr: HashBuiltin*,
syscall_ptr: felt*,
pedersen_ptr: HashBuiltin*,
syscall_ptr: felt*,
range_check_ptr
}(_from: felt, to: felt, token_id: Uint256):
alloc_locals
Expand All @@ -218,21 +218,21 @@ func ERC721_transferFrom{
# Note that if either `is_approved` or `caller` equals `0`,
# then this method should fail.
# The `caller` address and `is_approved` boolean are both field elements
# meaning that a*0==0 for all a in the field,
# therefore a*b==0 implies that at least one of a,b is zero in the field
# meaning that a*0==0 for all a in the field,
# therefore a*b==0 implies that at least one of a,b is zero in the field

_transfer(_from, to, token_id)
return ()
end

func ERC721_safeTransferFrom{
pedersen_ptr: HashBuiltin*,
syscall_ptr: felt*,
pedersen_ptr: HashBuiltin*,
syscall_ptr: felt*,
range_check_ptr
}(
_from: felt,
to: felt,
token_id: Uint256,
_from: felt,
to: felt,
token_id: Uint256,
data_len: felt,
data: felt*
):
Expand All @@ -244,16 +244,16 @@ func ERC721_safeTransferFrom{
# Note that if either `is_approved` or `caller` equals `0`,
# then this method should fail.
# The `caller` address and `is_approved` boolean are both field elements
# meaning that a*0==0 for all a in the field,
# meaning that a*0==0 for all a in the field,
# therefore a*b==0 implies that at least one of a,b is zero in the field

_safe_transfer(_from, to, token_id, data_len, data)
return ()
end

func ERC721_mint{
pedersen_ptr: HashBuiltin*,
syscall_ptr: felt*,
pedersen_ptr: HashBuiltin*,
syscall_ptr: felt*,
range_check_ptr
}(to: felt, token_id: Uint256):
uint256_check(token_id)
Expand All @@ -271,8 +271,8 @@ func ERC721_mint{
end

func ERC721_burn{
pedersen_ptr: HashBuiltin*,
syscall_ptr: felt*,
pedersen_ptr: HashBuiltin*,
syscall_ptr: felt*,
range_check_ptr
}(token_id: Uint256):
alloc_locals
Expand All @@ -293,30 +293,32 @@ func ERC721_burn{
end

func ERC721_safeMint{
pedersen_ptr: HashBuiltin*,
syscall_ptr: felt*,
pedersen_ptr: HashBuiltin*,
syscall_ptr: felt*,
range_check_ptr
}(
to: felt,
token_id: Uint256,
data_len: felt,
to: felt,
token_id: Uint256,
data_len: felt,
data: felt*
):
uint256_check(token_id)
ERC721_mint(to, token_id)
_check_onERC721Received(

let (success) = _check_onERC721Received(
0,
to,
token_id,
data_len,
data_len,
data
)
assert_not_zero(success)
return ()
end

func ERC721_only_token_owner{
pedersen_ptr: HashBuiltin*,
syscall_ptr: felt*,
pedersen_ptr: HashBuiltin*,
syscall_ptr: felt*,
range_check_ptr
}(token_id: Uint256):
uint256_check(token_id)
Expand All @@ -328,8 +330,8 @@ func ERC721_only_token_owner{
end

func ERC721_setTokenURI{
syscall_ptr: felt*,
pedersen_ptr: HashBuiltin*,
syscall_ptr: felt*,
pedersen_ptr: HashBuiltin*,
range_check_ptr
}(token_id: Uint256, token_uri: felt):
uint256_check(token_id)
Expand All @@ -345,17 +347,17 @@ end
#

func _approve{
syscall_ptr: felt*,
pedersen_ptr: HashBuiltin*,
syscall_ptr: felt*,
pedersen_ptr: HashBuiltin*,
range_check_ptr
}(to: felt, token_id: Uint256):
ERC721_token_approvals.write(token_id, to)
return ()
end

func _is_approved_or_owner{
pedersen_ptr: HashBuiltin*,
syscall_ptr: felt*,
pedersen_ptr: HashBuiltin*,
syscall_ptr: felt*,
range_check_ptr
}(spender: felt, token_id: Uint256) -> (res: felt):
alloc_locals
Expand All @@ -382,8 +384,8 @@ func _is_approved_or_owner{
end

func _exists{
syscall_ptr: felt*,
pedersen_ptr: HashBuiltin*,
syscall_ptr: felt*,
pedersen_ptr: HashBuiltin*,
range_check_ptr
}(token_id: Uint256) -> (res: felt):
let (res) = ERC721_owners.read(token_id)
Expand All @@ -396,8 +398,8 @@ func _exists{
end

func _transfer{
syscall_ptr: felt*,
pedersen_ptr: HashBuiltin*,
syscall_ptr: felt*,
pedersen_ptr: HashBuiltin*,
range_check_ptr
}(_from: felt, to: felt, token_id: Uint256):
# ownerOf ensures '_from' is not the zero address
Expand Down Expand Up @@ -425,12 +427,12 @@ func _transfer{
end

func _safe_transfer{
syscall_ptr: felt*,
pedersen_ptr: HashBuiltin*,
syscall_ptr: felt*,
pedersen_ptr: HashBuiltin*,
range_check_ptr
}(
_from: felt,
to: felt,
_from: felt,
to: felt,
token_id: Uint256,
data_len: felt,
data: felt*
Expand All @@ -443,26 +445,26 @@ func _safe_transfer{
end

func _check_onERC721Received{
syscall_ptr: felt*,
pedersen_ptr: HashBuiltin*,
syscall_ptr: felt*,
pedersen_ptr: HashBuiltin*,
range_check_ptr
}(
_from: felt,
to: felt,
_from: felt,
to: felt,
token_id: Uint256,
data_len: felt,
data_len: felt,
data: felt*
) -> (success: felt):
let (caller) = get_caller_address()
# ERC721_RECEIVER_ID = 0x150b7a02
let (is_supported) = IERC165.supportsInterface(to, 0x150b7a02)
if is_supported == TRUE:
let (selector) = IERC721_Receiver.onERC721Received(
to,
caller,
_from,
token_id,
data_len,
to,
caller,
_from,
token_id,
data_len,
data
)

Expand Down

0 comments on commit 88038a7

Please sign in to comment.