The Saudis, a popular NFT project, started a freemint campaign on July 10, 2022 where whitelisted users can mint their NFTs for free. A user identified as RIGHTBLOCK dumped a substantial quantity of NFT into the market shortly after the mint event concluded. Swift action was taken by the project team to lock the user’s account and modify the contract to remove a sizable number of NFTs from the user’s control. A promise was made to return these NFTs back to the community in the near future.
The question is, why are project developers able to transfer the NFTs from the user’s control? After doing some research, we found that the NFT project’s contract uses the EIP-2535 protocol, which is also called the “diamond protocol.” This protocol is used by the project team to modify the contract’s functionalities in order to implement these NFT transfers. The SlowMist security team will now proceed to explain the finer points of the Diamond Protocol (EIP-2535).
Introduction to the Diamond Protocol
The Ethereum Improvement Proposal (EIP)-2535 proposes a method for organizing the various components of an Ethereum smart contract. Its purpose is to facilitate the modification of contract functionality and allow smart contracts to exceed the maximum size limit of 24KB.
In order to fully grasp the Diamond Protocol, it is essential to have a working knowledge of the following terms and their respective definitions:
- Diamond: Diamond is the principal contract that interacts with users and can be regarded as a proxy contract (Proxy).
- Facet: A diamond contract has various faces, just as a genuine diamond has multiple sides. Each function called in the contract corresponds to a distinct aspect. It can also be understood as an implementation contract (Implementation)
- Diamond Cut: The Diamond Cut function is extended in the Diamond Protocol Standard. Its primary purpose is to improve contracts by adding, replacing, or removing facets and functionalities from diamonds.
- The Loupe: The primary purpose in the diamond protocol standard is to return the information about the facet and the existence of the diamond. This is stored in the storage structure inside the diamond contract — DiamondStorage
This is what the complete diamond model looks like:
When a diamond contract is written in accordance with the Diamond Standard Specification, its code may reference the code of any number of other faceted contracts. The code of the corresponding distinct facet contracts must be called to implement different functions in the diamond contract, and the function of diamond cutting may be used to edit (add, replace, or remove) various functions in the diamond contract.
This differs from the majority of existing methods, which employ a proxy contract and an implementation contract to facilitate interaction and upgrades.
Let’s go back and look at some of the nuances in The Saudi project. The function that implements the diamondCut function can be found in the project’s DiamondCutFacet.sol contract.
The code will first use the LibDiamond library’s ‘enforceIsContractOwner’ function to determine if the caller is the contract’s owner. If called by the owner, it will use the LibDiamond library’s ‘diamondCut’ function to modify the diamond contract’s function.
Following up on this function, we discovered that diamond cut will evaluate the addition, replacement, and removal actions based on the various incoming actions. Let’s follow that and see where it leads.
We discovered that a new, closed-source contract
0x70d8ccaf6b50b051ab1e8c26163e45a8b03 was passed. If the incoming action is set to ‘1’, it should call ‘replaceFunctions’ to implement the replacement function.
The “replaceFunctions” denotes that the function will first add a new facet to an incoming address, and then delete the old facet from the address by retrieving it from the storage after each function selector has been supplied. A new facet gets added as an address is passed in.
Based on what has been gathered so far, it seems that a member of the Saudi project team rewrote the transfer function using the diamond cutting function in order to retrieve the NFT from RIGHTBLOCK.
Saudis NFT Contract Address: 0xe21ebcd28d37a67757b9bc7b290f4c4928a430b1
User RIGHTBLOCK Address: 0x80266b1e3f0C2cAdAE65A4Ef5Df20f3DF3707FfB
Transaction Id of updated contract: