Skip to content

Commit

Permalink
add burn function (#243)
Browse files Browse the repository at this point in the history
* add burn function

* remove formatting

* unit test for burn function

* only token owner can burn a token

* should panic if wrong owner try to burn token

* rename test function name
  • Loading branch information
mubarak23 authored Oct 7, 2024
1 parent 229d3dc commit b78a45d
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 2 deletions.
71 changes: 70 additions & 1 deletion apps/blockchain/starknet/src/token/erc721_bridgeable.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,13 @@ mod erc721_bridgeable {
self.erc721._mint(to, token_id);
}

fn burn(ref self: ContractState, token_id: u256) {
let token_owner = self.erc721.owner_of(token_id);
assert(token_owner == starknet::get_caller_address(), 'ERC721: only owner can burn');
self.erc721._burn(token_id);
}


fn mint_from_bridge_uri(ref self: ContractState, to: ContractAddress, token_id: u256, token_uri: ByteArray) {
IERC721Bridgeable::mint_from_bridge(ref self, to, token_id);
self.token_uris.write(token_id, token_uri);
Expand Down Expand Up @@ -296,6 +303,68 @@ mod tests {
assert_eq!(erc721.token_uri(0), "myuri", "bad uri");
}


/// Should burn token from bridge call.
#[test]
fn test_burn_token() {
let BRIDGE = bridge_addr_mock();

let DUO_OWNER = starknet::contract_address_const::<128>();

let contract_address = deploy_everai_collection();

let erc721b = IERC721BridgeableDispatcher { contract_address };

// Mint a token first to be able to burn it later
start_prank(CheatTarget::One(contract_address), BRIDGE);
erc721b.mint_from_bridge(DUO_OWNER, 42_u256);
stop_prank(CheatTarget::One(contract_address));

// Check that the owner is set correctly after minting
let erc721 = IERC721Dispatcher { contract_address };
assert!(erc721.owner_of(42_u256) == DUO_OWNER, "bad owner after mint");

// Burn the token
start_prank(CheatTarget::One(contract_address), DUO_OWNER);
erc721b.burn(42_u256);
stop_prank(CheatTarget::One(contract_address));

// balance_of

let balance = erc721.balance_of(DUO_OWNER);
assert(balance == 0, 'token was not burn');


}

/// Should panic, only owner can burn
#[test]
#[should_panic(expected: ('ERC721: only owner can burn', ))]
fn should_panic_test_burn_token() {
let BRIDGE = bridge_addr_mock();

let DUO_OWNER = starknet::contract_address_const::<128>();

let contract_address = deploy_everai_collection();

let erc721b = IERC721BridgeableDispatcher { contract_address };

// Mint a token first to be able to burn it later
start_prank(CheatTarget::One(contract_address), BRIDGE);
erc721b.mint_from_bridge(DUO_OWNER, 42_u256);
stop_prank(CheatTarget::One(contract_address));

// Check that the owner is set correctly after minting
let erc721 = IERC721Dispatcher { contract_address };
assert!(erc721.owner_of(42_u256) == DUO_OWNER, "bad owner after mint");

// Burn the token by wrong owner
start_prank(CheatTarget::One(contract_address), BRIDGE);
erc721b.burn(42_u256);


}

/// Should not mint token if not bridge.
#[test]
#[should_panic(expected: ('ERC721: only bridge can mint', ))]
Expand Down Expand Up @@ -512,4 +581,4 @@ mod tests {
assert_eq!(IERC721Dispatcher {contract_address}.token_uri(token_id), new_uri);
}

}
}
4 changes: 3 additions & 1 deletion apps/blockchain/starknet/src/token/interfaces.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ trait IERC721<T> {
fn owner_of(self: @T, token_id: u256) -> ContractAddress;
fn token_uri(self: @T, token_id: u256) -> ByteArray;
fn is_approved_for_all(self: @T, owner: ContractAddress, operator: ContractAddress) -> bool;

fn balance_of(self: @T, owner: ContractAddress) -> u256;
fn set_approval_for_all(ref self: T, operator: ContractAddress, approved: bool);
fn transfer_from(ref self: T, from: ContractAddress, to: ContractAddress, token_id: u256);
fn approve(ref self: T, to: ContractAddress, token_id: u256);
Expand All @@ -30,6 +30,8 @@ trait IERC721Mintable<T> {
/// ERC721 that can be manipulated by the bridge.
#[starknet::interface]
trait IERC721Bridgeable<T> {
fn burn(ref self: T, token_id: u256);

fn mint_from_bridge(ref self: T, to: ContractAddress, token_id: u256);

fn mint_from_bridge_uri(ref self: T, to: ContractAddress, token_id: u256, token_uri: ByteArray);
Expand Down

0 comments on commit b78a45d

Please sign in to comment.