The AddressProvider serves as the entry point contract for Curve's various registries and is deployed on all chains where Curve is operational. The contract holds the most important contract addresses.
GitHub
Source code of the AddressProvider.vy contract can be found on GitHub. A list of all deployed contracts can be found here.
Contract Upgradability
The AddressProvider contract is managed by an admin who is currently an individual at Curve, rather than the Curve DAO1. This admin has the ability to update, add or remove new IDs within the contract. When integrating this contract into systems or relying on it for critical components, it is essential to consider that these IDs and their associated addresses can be modified at any time.
For the full mapping of IDs please see get_id_info.
ID information is stored in a struct, containing an address, a detailed description, its version, and the timestamp marking its most recent modification:
A Google Colab notebook that provides a full mapping of IDs by iterating over all ids via calling the get_id_info can be found here: Google Colab Notebook
The notebook is compatible with querying IDs for different chains and returns a table as shown below:
Getter function for all the IDs of active registry items in the AddressProvider.
Returns: active ids (DynArray[uint256, 1000])
Source code
_ids:DynArray[uint256,1000]@view@externaldefids()->DynArray[uint256,1000]:""" @notice returns IDs of active registry items in the AddressProvider. @returns An array of IDs. """_ids:DynArray[uint256,1000]=[]for_idinself._ids:ifself.check_id_exists[_id]:_ids.append(_id)return_ids
This method returns the address of the contract, the description, the ID version (which is incremented by 1 each time the ID is updated), and the timestamp of the last modification. When calling the function for an unpopulated ID, it returns an empty AddressInfo struct.
>>>AddressProvider.get_id_info(0)'0x90E00ACe148ca3b23Ac1bC8C240C2a7Dd9c2d7f5, Stableswap Custom Pool Registry, 1, 1712655599'>>>AddressProvider.get_id_info(9)'0x0000000000000000000000000000000000000000, '', 0, 0'
structAddressInfo:addr:addressdescription:String[256]version:uint256last_modified:uint256get_id_info:public(HashMap[uint256,AddressInfo])@view@externaldefget_address(_id:uint256)->address:""" @notice Fetch the address associated with `_id` @dev Returns empty(address) if `_id` has not been defined, or has been unset @param _id Identifier to fetch an address for @return Current address associated to `_id` """returnself.get_id_info[_id].addr
IDs can be added, removed, or adjusted by the admin of the contract.
Contract Upgradability
The AddressProvider contract is managed by an admin who is currently an individual at Curve, rather than the Curve DAO1. This admin has the ability to update, add or remove new IDs within the contract. When integrating this contract into systems or relying on it for critical components, it is essential to consider that these IDs and their associated addresses can be modified at any time.
This function can only be called by the admin of the contract.
Function to update the address and description of an ID.
Emits: EntryModified
Input
Type
Description
_id
uint256
ID to update
_new_address
address
New address
_new_description
String[64]
New description
Source code
eventEntryModified:id:indexed(uint256)version:uint256@externaldefupdate_id(_id:uint256,_new_address:address,_new_description:String[64],):""" @notice Update entries at an ID @param _id Address assigned to the input _id @param _new_address Address assigned to the _id @param _new_description Human-readable description of the identifier """assertmsg.sender==self.admin# dev: admin-only functionassertself.check_id_exists[_id]# dev: id does not exist# Update entry at _id:self.get_id_info[_id].addr=_new_addressself.get_id_info[_id].description=_new_description# Update metadata (version, update time):self._update_entry_metadata(_id)@internaldef_update_entry_metadata(_id:uint256):version:uint256=self.get_id_info[_id].version+1self.get_id_info[_id].version=versionself.get_id_info[_id].last_modified=block.timestamplogEntryModified(_id,version)
This function can only be called by the admin of the contract.
Function to update the address of an ID.
Emits: EntryModified
Input
Type
Description
_id
uint256
ID to change the address for
_address
address
New address to change it to
Source code
eventEntryModified:id:indexed(uint256)version:uint256check_id_exists:public(HashMap[uint256,bool])get_id_info:public(HashMap[uint256,AddressInfo])@externaldefupdate_address(_id:uint256,_address:address):""" @notice Set a new address for an existing identifier @param _id Identifier to set the new address for @param _address Address to set """assertmsg.sender==self.admin# dev: admin-only functionassertself.check_id_exists[_id]# dev: id does not exist# Update address:self.get_id_info[_id].addr=_address# Update metadata (version, update time):self._update_entry_metadata(_id)@internaldef_update_entry_metadata(_id:uint256):version:uint256=self.get_id_info[_id].version+1self.get_id_info[_id].version=versionself.get_id_info[_id].last_modified=block.timestamplogEntryModified(_id,version)
This function can only be called by the admin of the contract.
Function to update the description of an ID.
Emits: EntryModified
Input
Type
Description
_id
uint256
ID to change the description for
_description
String[256]
New description
Source code
eventEntryModified:id:indexed(uint256)version:uint256check_id_exists:public(HashMap[uint256,bool])get_id_info:public(HashMap[uint256,AddressInfo])@externaldefupdate_description(_id:uint256,_description:String[256]):""" @notice Update description for an existing _id @param _id Identifier to set the new description for @param _description New description to set """assertmsg.sender==self.admin# dev: admin-only functionassertself.check_id_exists[_id]# dev: id does not exist# Update description:self.get_id_info[_id].description=_description# Update metadata (version, update time):self._update_entry_metadata(_id)@internaldef_update_entry_metadata(_id:uint256):version:uint256=self.get_id_info[_id].version+1self.get_id_info[_id].version=versionself.get_id_info[_id].last_modified=block.timestamplogEntryModified(_id,version)
This function can only be called by the admin of the contract.
Function to add a new registry item to the AddressProvider.
Emits: NewEntry
Input
Type
Description
_id
uint256
ID to add; Reverts if ID number is already used
_address
address
New address
_description
String[64]
New description
Source code
eventNewEntry:id:indexed(uint256)addr:addressdescription:String[64]@externaldefadd_new_id(_id:uint256,_address:address,_description:String[64],):""" @notice Enter a new registry item @param _id ID assigned to the address @param _address Address assigned to the ID @param _description Human-readable description of the ID """assertmsg.sender==self.admin# dev: admin-only functionself._add_new_id(_id,_address,_description)@internaldef_add_new_id(_id:uint256,_address:address,_description:String[64]):assertnotself.check_id_exists[_id]# dev: id existsself.check_id_exists[_id]=Trueself._ids.append(_id)# Add entry:self.get_id_info[_id]=AddressInfo({addr:_address,description:_description,version:1,last_modified:block.timestamp,})self.num_entries+=1logNewEntry(_id,_address,_description)
This function can only be called by the admin of the contract.
Function to add mutiple new registry items to the AddressProvider at once.
Emits: NewEntry
Input
Type
Description
_ids
DynArray[uint256, 25]
IDs to add; Reverts if ID number is already used
_addresss
DynArray[address, 25]
ID addresses
_descriptions
DynArray[String[64], 25]
ID descriptions
Source code
eventNewEntry:id:indexed(uint256)addr:addressdescription:String[64]@externaldefadd_new_ids(_ids:DynArray[uint256,25],_addresses:DynArray[address,25],_descriptions:DynArray[String[64],25],):""" @notice Enter new registry items @param _ids IDs assigned to addresses @param _addresses Addresses assigned to corresponding IDs @param _descriptions Human-readable description of each of the IDs """assertmsg.sender==self.admin# dev: admin-only function# Check lengthsassertlen(_ids)==len(_addresses)assertlen(_addresses)==len(_descriptions)foriinrange(len(_ids),bound=20):self._add_new_id(_ids[i],_addresses[i],_descriptions[i])@internaldef_add_new_id(_id:uint256,_address:address,_description:String[64]):assertnotself.check_id_exists[_id]# dev: id existsself.check_id_exists[_id]=Trueself._ids.append(_id)# Add entry:self.get_id_info[_id]=AddressInfo({addr:_address,description:_description,version:1,last_modified:block.timestamp,})self.num_entries+=1logNewEntry(_id,_address,_description)
This function can only be called by the admin of the contract.
Function to remove a registry item from the AddressProvider.
Returns: true (bool).
Emits: EntryRemoved
Input
Type
Description
_id
uint256
ID to remove
Source code
eventEntryRemoved:id:indexed(uint256)@externaldefremove_id(_id:uint256)->bool:""" @notice Unset an existing identifier @param _id Identifier to unset @return bool success """assertmsg.sender==self.admin# dev: admin-only functionreturnself._remove_id(_id)@internaldef_remove_id(_id:uint256)->bool:assertself.check_id_exists[_id]# dev: id does not exist# Clear ID:self.get_id_info[_id].addr=empty(address)self.get_id_info[_id].last_modified=0self.get_id_info[_id].description=''self.get_id_info[_id].version=0self.check_id_exists[_id]=False# Reduce num entries:self.num_entries-=1# Emit 0 in version to notify removal of id:logEntryRemoved(_id)returnTrue
This function can only be called by the admin of the contract.
Function to remove mutiple registry items from the AddressProvider at once.
Returns: true (bool).
Emits: EntryRemoved
Input
Type
Description
_ids
DynArray[uint256, 20]
IDs to remove
Source code
eventEntryRemoved:id:indexed(uint256)@externaldefremove_ids(_ids:DynArray[uint256,20])->bool:""" @notice Unset existing identifiers @param _id DynArray of identifier to unset @return bool success """assertmsg.sender==self.admin# dev: admin-only functionfor_idin_ids:assertself._remove_id(_id)returnTrue@internaldef_remove_id(_id:uint256)->bool:assertself.check_id_exists[_id]# dev: id does not exist# Clear ID:self.get_id_info[_id].addr=empty(address)self.get_id_info[_id].last_modified=0self.get_id_info[_id].description=''self.get_id_info[_id].version=0self.check_id_exists[_id]=False# Reduce num entries:self.num_entries-=1# Emit 0 in version to notify removal of id:logEntryRemoved(_id)returnTrue
This function can only be called by the admin of the contract.
Function to initiate a transfer of contract ownership.
Returns: true (bool).
Events: CommitNewAdmin
Input
Type
Description
_new_admin
address
Address to transfer the ownership to
Source code
eventCommitNewAdmin:admin:indexed(address)future_admin:public(address)@externaldefcommit_transfer_ownership(_new_admin:address)->bool:""" @notice Initiate a transfer of contract ownership @dev Once initiated, the actual transfer may be performed three days later @param _new_admin Address of the new owner account @return bool success """assertmsg.sender==self.admin# dev: admin-only functionself.future_admin=_new_adminlogCommitNewAdmin(_new_admin)returnTrue
This function can only be called by the future_admin of the contract.
Function to finalize a transfer of contract ownership.
Returns: true (bool).
Emits: NewAdmin
Source code
eventNewAdmin:admin:indexed(address)admin:public(address)future_admin:public(address)@externaldefapply_transfer_ownership()->bool:""" @notice Finalize a transfer of contract ownership @dev May only be called by the next owner @return bool success """assertmsg.sender==self.future_admin# dev: admin-only functionnew_admin:address=self.future_adminself.admin=new_adminlogNewAdmin(new_admin)returnTrue
This function can only be called by the admin of the contract.
Function to revert the transfer of contract ownership.
Returns: true (bool).
Source code
admin:public(address)future_admin:public(address)@externaldefrevert_transfer_ownership()->bool:""" @notice Revert a transfer of contract ownership @dev May only be called by the current owner @return bool success """assertmsg.sender==self.admin# dev: admin-only functionself.future_admin=empty(address)returnTrue
>>>soon
Reasoning: Due to the nature of the contract (it does not hold any user funds or has any monetary influence), it is not considered a crucial contract. It should only be used as a pure informational source. Additionally, the Curve ecosystem changes very rapidly and therefore requires fast updates for such a contract. Always putting up a DAO vote to change IDs would not be feasible. ↩↩