일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 스마트컨트렉트테스트
- erc4337
- ethers websocket
- 머신러닝기초
- ambiguous function description
- 계정추상화
- Vue
- erc4337 contract
- rust 기초
- 체인의정석
- 러스트기초
- 스마트 컨트렉트 함수이름 중복
- SBT표준
- 러스트 기초 학습
- Vue.js
- chainlink 설명
- 컨트렉트 동일한 함수이름 호출
- vue기초
- 스마트컨트렉트 함수이름 중복 호출
- 컨트렉트 배포 자동화
- multicall
- 스마트컨트렉트 예약어 함수이름 중복
- ethers
- 티스토리챌린지
- 러스트 기초
- ethers type
- ethers typescript
- ethers v6
- git rebase
- 오블완
- Today
- Total
체인의정석
ERC721의 safeTransferFrom 본문
safeTransferFrom 같은 경우
ERC721 onRECEIVE를 상속 받았는지 여부를 체크해 준다.
스마트컨트렉트가 받는 주소라면 이렇게 transferFrom을 사용하여야지 안에 토큰들이 갇히는 걸 방지할 수 있다.
기본적으로 오픈제플린에서 상속을 받으면 safeTransferFrom 이 적용된다.
하지만 직접적으로 토큰을 다루는 컨트렉트 들은
function onERC721Received(
address,
address,
uint256,
bytes memory
)
public
returns (bytes4)
{
return this.onERC721Received.selector;
}
"IERC721Receiver" 인터페이스를 상속 받은 후 위와 같이 오버라이딩 해주어야 한다.
위는 0.5.0 버전으로 하엿지만 최신 버전에는 override를 넣어준다.
이러한 작업을 해서 해당 컨트렉트가 Receiver를 구현했을 경우에만 토큰을 보내면 보낼때 만약 transferFrom으로 받는 함수가 있어야지만 받는다. 실제로 transferFrom과 safeTransferFrom은 위의 인터페이스를 구현했는지 여부를 두며, 위의 인터페이스에서는 transferFrom에 대한 함수가 바이트로 변환되어 들어가 있기 때문에. 만약, 해당 함수가 있을 경우라면 실행을 해주고 위와 같이 Receiver가 체크를 안해주면 실행이 안되는 원리이다.
pragma solidity ^0.5.0;
/**
* @title ERC721 token receiver interface
* @dev Interface for any contract that wants to support safeTransfers
* from ERC721 asset contracts.
*/
contract IERC721Receiver {
/**
* @notice Handle the receipt of an NFT
* @dev The ERC721 smart contract calls this function on the recipient
* after a `safeTransfer`. This function MUST return the function selector,
* otherwise the caller will revert the transaction. The selector to be
* returned can be obtained as `this.onERC721Received.selector`. This
* function MAY throw to revert and reject the transfer.
* Note: the ERC721 contract address is always the message sender.
* @param operator The address which called `safeTransferFrom` function
* @param from The address which previously owned the token
* @param tokenId The NFT identifier which is being transferred
* @param data Additional data with no specified format
* @return bytes4 `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
*/
function onERC721Received(address operator, address from, uint256 tokenId, bytes memory data)
public returns (bytes4);
}
위와 같이 오픈제플린의 주석을 보면 retruned를 obtain하는 방법이 나와 있어 맨 위에 있는 코드와 같이 리턴을 해주는 것이다.
또한 safeTransferFrom은 ethers.js에서 구현할 때 다른 함수와는 조금 다른 방식을 취하는데 그 이유는 함수를 오버라이딩 된걸 받아오기 때문이다.
ethers.js에서 safeTransferFrom을 다루는 것은
https://forum.openzeppelin.com/t/where-is-safefromtransfer-function-in-contract-instance/12020
위와 같이 다른것과 다르게 오버로딩 된 함수이므로
Wrong:
contract.safeTransferFrom(addr1, addr2, 1);
Correct:
contract["safeTransferFrom(address,address,uint256)"](addr1, addr2, 1);
아래와 같이 사용하여 준다.
await expect(exampleERC721.connect(addr2).transferFrom(addr1.address,addr2.address,tokenId))
.to.emit(exampleERC721, "Transfer")
.withArgs(addr1.address,addr2.address,tokenId)
await expect(exampleERC721.connect(addr1)["safeTransferFrom(address,address,uint256)"](addr2.address,addr1.address,tokenId))
.to.emit(exampleERC721, "Transfer")
.withArgs(addr2.address,addr1.address,tokenId)
위와 아래를 비교해보면 그 차이를 알 수 있다.
이렇게 오버라이딩된 것을 고려하여 테스트코드 까지 작성하면 토큰을 받아와서 금고처럼 사용하거나 플랫폼 처럼 사용하는 컨트렉트에서 safeTransferFrom에 대비할 수 있다.
'블록체인 > NFT & BRIDGE' 카테고리의 다른 글
트레블룰을 만족하는 크로스체인 NFT 브릿지 , 논문 계획서 초안 (0) | 2022.02.20 |
---|---|
스마트컨트렉트 디버깅 하기) erc721 burn에 대한 테스트 오류 해결 (0) | 2022.02.14 |
Solidity 에서 token URI 와 toString 라이브러리 (0) | 2022.02.09 |
ERC721 Receiver에 대한 설명 (0) | 2022.02.08 |
ERC721) token URI에 대한 코드 분석 (0) | 2022.02.08 |