交易所開發(穩定版)/交易所繫統開發(python開發)/交易所開發(原始碼版)

開發MrsFu123發表於2023-04-23

  智慧合約簡單說,它是一種用計算機語言取代法律語言去記錄條款的合約,可以由一個計算系統自動執行。


  更簡單地說,智慧合約就是傳統合約的數字化版本。


  如果說區塊鏈是一個資料庫,智慧合約就是能夠使區塊鏈技術應用到現實當中的應用層。


  智慧合約是在區塊鏈資料庫上執行的計算機程式,可以在滿足其原始碼中寫入的條件時自行執行。


  function _transfer(


  address from,


  address to,


  uint256 tokenId


  )internal virtual{


  //前置檢查:被轉移的代幣屬於from使用者


  require(ERC721.ownerOf(tokenId)==from,"ERC721:transfer from incorrect owner");


  //前置檢查:接收代幣的使用者to不能為零地址


  require(to!=address(0),"ERC721:transfer to the zero address");


  //鉤子函式:代幣轉移前觸發,官方實現無做實際操作,如果業務有特殊的邏輯,我理解可重寫_beforeTokenTransfer函式


  _beforeTokenTransfer(from,to,tokenId);


  //清除之前的授權—————指向零地址


  _approve(address(0),tokenId);


  //from賬號代幣數-1


  _balances[from]-=1;


  //to賬號代幣數+1


  _balances[to]+=1;


  //執行代幣的轉移,即更換owner地址


  _owners[tokenId]=to;


  //觸發轉移事件


  emit Transfer(from,to,tokenId);


  //鉤子函式:代幣轉移後觸發,官方實現無做實際操作


  _afterTokenTransfer(from,to,tokenId);


  }


  /**


  *dev See{IERC721-safeTransferFrom}.


  *安全代幣轉移,真實中使用該函式比較合適。


  */


  function safeTransferFrom(


  address from,


  address to,


  uint256 tokenId


  )public virtual override{


  safeTransferFrom(from,to,tokenId,"");


  }


  /**


  *dev See{IERC721-safeTransferFrom}.


  *安全轉移函式,攜帶回撥資料_data


  */


  function safeTransferFrom(


  address from,


  address to,


  uint256 tokenId,


  bytes memory _data


  )public virtual override{


  //前置檢查:函式呼叫者是tokenID的owner或者擁有操作許可權


  require(_isApprovedOrOwner(_msgSender(),tokenId),"ERC721:transfer caller is not owner nor approved");


  //內部函式,執行真正的安全轉移


  _safeTransfer(from,to,tokenId,_data);


  }


  /**


  *dev Safely transfers`tokenId`token from`from`to`to`,checking first that contract recipients


  *are aware of the ERC721 protocol to prevent tokens from being forever locked.


  *`_data`is additional data,it has no specified format and it is sent in call to`to`.


  *This internal function is equivalent to{safeTransferFrom},and can be used to e.g.


  *implement alternative mechanisms to perform token transfer,such as signature-based.


  *


  *Requirements:


  *-`from`cannot be the zero address.


  *-`to`cannot be the zero address.


  *-`tokenId`token must exist and be owned by`from`.


  *-If`to`refers to a smart contract,it must implement{IERC721Receiver-onERC721Received},which is called upon a safe transfer.


  *


  *Emits a{Transfer}event.


  */


  function _safeTransfer(


  address from,


  address to,


  uint256 tokenId,


  bytes memory _data


  )internal virtual{


  //內部函式:執行轉移


  _transfer(from,to,tokenId);


  //安全的由來:代幣接收者如果是一個合約,那麼其必須要實現IERC721Receiver規範,否則轉移失敗


  require(_checkOnERC721Received(from,to,tokenId,_data),"ERC721:transfer to non ERC721Receiver implementer");


  }


  /**


  *dev Returns whether`tokenId`exists.


  *內部函式,判斷代幣是否存在


  */


  function _exists(uint256 tokenId)internal view virtual returns(bool){


  return _owners[tokenId]!=address(0);


  }


  /**


  *dev Safely mints`tokenId`and transfers it to`to`.


  *Requirements:


  *-`tokenId`must not exist.


  *-If`to`refers to a smart contract,it must implement{IERC721Receiver-onERC721Received},which is called upon a safe transfer.


  *Emits a{Transfer}event.


  *內部函式:安全鑄造NFT,我們編寫的合約在鑄造NFT的時候,呼叫的就是該方法。


  */


  function _safeMint(address to,uint256 tokenId)internal virtual{


  //內部函式:鑄造


  _safeMint(to,tokenId,"");


  }


  /**


  *真實鑄造NFT函式,內部函式


  */


  function _safeMint(


  address to,


  uint256 tokenId,


  bytes memory _data


  )internal virtual{


  //鑄造


  _mint(to,tokenId);


  //判斷接收者是否是合約,如果是合約則需要實現ERC721Receiver規範。


  require(


  _checkOnERC721Received(address(0),to,tokenId,_data),


  "ERC721:transfer to non ERC721Receiver implementer"


  );


  }


  /**


  *dev Mints`tokenId`and transfers it to`to`.


  *Requirements:


  *-`tokenId`must not exist.


  *-`to`cannot be the zero address.


  *Emits a{Transfer}event.


  *內部函式:鑄造代幣,但是我們一般不直接呼叫該函式;呼叫_safeMint更安全


  */


  function _mint(address to,uint256 tokenId)internal virtual{


  //前置檢查:代幣接收者不能是零地址


  require(to!=address(0),"ERC721:mint to the zero address");


  //前置檢查:代幣的tokenID不能是已存在的(獨一無二)


  require(!_exists(tokenId),"ERC721:token already minted");


  //鉤子函式:代幣轉移前觸發


  _beforeTokenTransfer(address(0),to,tokenId);


  //to賬號代幣數+1


  _balances[to]+=1;


  //代幣歸屬


  _owners[tokenId]=to;


  //觸發轉移實現,從零地址發起,說明是鑄造生成


  emit Transfer(address(0),to,tokenId);


  //鉤子函式:代幣轉移後觸發


  _afterTokenTransfer(address(0),to,tokenId);


  }


  /**


  *dev Destroys`tokenId`.


  *The approval is cleared when the token is burned.


  *Requirements:


  *-`tokenId`must exist.


  *Emits a{Transfer}event.


  *內部函式:代幣銷燬


  *注意:函式並沒有做許可權檢查。所以我們在我們的合約中如果要呼叫該函式,需要自己做tokenID的所有權檢查!


  */


  function _burn(uint256 tokenId)internal virtual{


  address owner=ERC721.ownerOf(tokenId);


  //鉤子函式:代幣轉移前觸發


  _beforeTokenTransfer(owner,address(0),tokenId);


  //清除授權


  _approve(address(0),tokenId);


  //使用者代幣數-1


  _balances[owner]-=1;


  //清理代幣


  delete _owners[tokenId];


  //觸發代幣轉移事件,代幣的接受者為零地址,說明是銷燬


  emit Transfer(owner,address(0),tokenId);


  //鉤子函式:代幣轉移後觸發


  _afterTokenTransfer(owner,address(0),tokenId);


  }


  /**


  *內部方法:判斷代幣接收者是否是合約,並且是否實現了IERC721Receiver介面


  *我們上面有介紹,如果代幣的接受者是一個合約的話,那麼合約需要實現IERC721Receiver介面


  */


  function _checkOnERC721Received(


  address from,


  address to,


  uint256 tokenId,


  bytes memory _data


  )private returns(bool){


  //接收者是合約


  if(to.isContract()){


  //判斷是否實現了IERC721Receiver


  try IERC721Receiver(to).onERC721Received(_msgSender(),from,tokenId,_data)returns(bytes4 retval){


  return retval==IERC721Receiver.onERC721Received.selector;


  }catch(bytes memory reason){


  if(reason.length==0){


  revert("ERC721:transfer to non ERC721Receiver implementer");


  }else{


  assembly{


  revert(add(32,reason),mload(reason))


  }


  }


  }


  }else{


  return true;


  }


  }


  /**


  *dev Hook that is called before any token transfer.This includes minting


  *and burning.


  *Calling conditions:


  *-When`from`and`to`are both non-zero,``from``'s`tokenId`will be


  *transferred to`to`.


  *-When`from`is zero,`tokenId`will be minted for`to`.


  *-When`to`is zero,``from``'s`tokenId`will be burned.


  *-`from`and`to`are never both zero.


  *To learn more about hooks,head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].


  *鉤子函式


  */


  function _beforeTokenTransfer(


  address from,


  address to,


  uint256 tokenId


  )internal virtual{}


  /**


  *dev Hook that is called after any transfer of tokens.This includes


  *minting and burning.


  *Calling conditions:


  *-when`from`and`to`are both non-zero.


  *-`from`and`to`are never both zero.


  *


  *To learn more about hooks,head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].


  *鉤子函式


  */


  function _afterTokenTransfer(


  address from,


  address to,


  uint256 tokenId


  )internal virtual{}


  }


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70016819/viewspace-2947862/,如需轉載,請註明出處,否則將追究法律責任。

相關文章