About the Unlock Smart Contract
The Unlock contract is a factory contract. Its main purpose is to create new locks based on a template. Additionally, it keeps track of locks after they have been created and grants Unlock tokens when new memberships have been purchased.
As of summer 2021, the unlock contract is owned by a multi-sig wallet managed by Unlock Inc. Our goal is to move toward decentralization by transferring ownership of the Unlock contact to the Unlock DAO.
This contract is upgradable using OpenZeppelin's upgradability framework. As of now, the ProxyAdmin is owned by a multi-sig wallet managed by Unlock Inc. Our goal is to move toward decentralization by transferring ownership of the Unlock contact to the Unlock DAO. Each implementation is versioned. The method
unlockVersion()
will yield the current version.Some functions that are deprecated or not implemented yet (no-op) have been omitted.
This function can be invoked by any Ethereum address and creates a new lock using the current template. (see below).
function createLock(
uint _expirationDuration, // Duration for each membership
address _tokenAddress, // Address of an ERC20 contract used as currency
uint _keyPrice, // Key price expressed in the ERC20 currency
uint _maxNumberOfKeys, // Maximum number of memberships which can be purchased
string calldata _lockName, // Name of the lock
bytes12 _salt // Unique salt used to compute the counterfactual lock address
) external returns(address); // Returns the addres of the lock
Once minted, the lock belongs to the caller of the function. The Unlock contract also keeps track of each locks' address.
This read-only function does not modify the state and yields the ERC721 base URL for metadata used by the locks. Each lock can override this.
function globalBaseTokenURI()
external
view
returns(string memory);
This read-only function does not modify the state and yields the ERC721 base token symbol used by the locks. Each lock can override this.
function globalTokenSymbol()
external
view
returns(string memory);
This read-only function does not modify the state and yields the network id on which this Unlock has been deployed. Some functionnality in the protocol differs based on the network (related to our governance token).
function chainId()
external
view
returns(uint);
This function modifies the state and sets multiple configuration parameters used by the protocol. It can be called several times in order to change the behavior of the protocol, but only by the owner of the Unlock contract.
function configUnlock(
address _udt, // Address of the UDT contract
address _weth, // Address of the wrapped Ethereum contract*
uint _estimatedGasForPurchase, // Amount of gas spent for each key purchase. Used to compute the UDT to be minted
string calldata _symbol, // Symbol of the ERC721 NFT
string calldata _URI, // Metadata URI for each ERC721
uint _chainId // network Id
)
external;
The
_weth
should be the chain's native token ERC20 (or wrapped as an ERC20). On Ethereum's main network, it is wrapped Ether for example.This function modifies the state and can only be called by the Unlock contract owner. It sets the template used to deploy locks. The address' should be a lock and its
initialize
and revokeOwnership
functions will be called. function setLockTemplate(
address payable _publicLockAddress
) external;
This function modifies the state and can only be called by the Unlock contract owner. It changes the gross network product value as well as the amount of discount granted. (note: as of summer 2021, it is unclear whether we will ever implement a discount mechanism, as we will let these decisions to the DAO).
function resetTrackedValue(
uint _grossNetworkProduct,
uint _totalDiscountGranted
) external;
This read-only function does not modify the state. The Unlock contract keeps track of all locks deployed by the protocol. It can be used to check if a lock was deployed using the protocol and yields a triplet of (boolean, total exchanged value recorded, amount of UDT yielded by this lock)
function locks(address) external view returns(bool deployed, uint totalSales, uint yieldedDiscountTokens);
This function modifies the state and can only be called by the Unlock contract owner. It adds an oracle to the list of oracles, for a specific token address. Since locks can be deployed using any ERC20, we need on-chain oracles to provide a conversion rate in order to compute the revenue added by each purchase.
function setOracle(
address _tokenAddress,
address _oracleAddress
) external;
This function modifies the state and can only be called by the Unlock contract owner. It lets the owner transfer ownership to another address. It is a highly sensitive function as the supplied address will get the full control of the protocol after the transfer. We expect this function to only be called to transfer ownership to DAO contracts.
function transferOwnership(address newOwner) external;
This function modifies the state and can only be called by the Unlock contract owner. It renounces ownership of the Unlock contract, thereby removing any functionality that is only available to the owner.
function renounceOwnership() external;
The functions below are getters (read-only functions).
// Total sales recorded by the protocol converted in the chains "native" currency
function grossNetworkProduct() external view returns(uint);
// The address of the public lock template, used when `createLock` is called
function publicLockAddress() external view returns(address);
// The WETH token address, used for value calculations
function weth() external view returns(address);
// The UDT token address, used to mint tokens on referral
function udt() external view returns(address);
// The approx amount of gas required to purchase a key
function estimatedGasForPurchase() external view returns(uint);
// The version number of the current Unlock implementation on this network
function unlockVersion() external pure returns(uint16);
// Returns the address of the current owner
function owner() external view returns(address);
// Returns the oracle address for a token address
function uniswapOracles(address) external view returns(address);