- This repo contains contracts to support:
- Highrise land and estates
- Funding contract to run the sales on our webpage
-
HighriseLandandHighriseEstatecontracts are ERC721 tokens representing parts of Highrise world that inherit following openzeppelin contracts:- ERC721Upgradeable
- ERC721EnumerableUpgradeable
- ERC721RoyaltyUpgradeable
- AccessControlUpgradeable
- Initializable
-
Both of these are supported to work on OpenSea.
- Owner of the contract for opensea is defined by
OWNER_ROLEin access control. - Gas-less listing is supported by overriding
isApprovedForAllmethod
- Owner of the contract for opensea is defined by
-
Estates can be constructed/deconstructed from/to land parcels. Supported shapes are 3x3, 6x6, 9x9 and 12x12
-
To create estates from land parcels user must first approve estate contract for transferring. This is achieved by ERC721
approvefunction inHighriseLandcontract and in custom batch approval functionapproveForTransferfunction inHighriseLandV2 -
Both Land and Estate contracts are intended to be upgradeable. This is done by using OpenZeppelin
TransparentUpgradeableProxyto separate the proxy and implementation contracts. This provides us with flexibility to add new logic and storage variables to the contracts in the future.
- Land coordinates are in range (-250, 250)
- Token ID is generated on Highrise backend with the following logic:
from struct import pack
def coordinates_to_token_id(coords: tuple[int, int]) -> int:
"""X and Y are 2 bytes each."""
as_bytes = pack(">hh", coords[0], coords[1])
return int.from_bytes(as_bytes, "big")- See https://docs.python.org/3/library/struct.html for more understanding.
- Estate contract has
token_id>coordinatesconversion function implemented. In that way estate contract can validate that parcels passed for estate creation have valid shape. - Two tests are implemented to validate
token_id<>coordinatesconversion works:test_coordinates_parsing- generates token id from coordinates in python and calls estate contract parse function. Compares that function returned coordinates match the ones initially used fortoken_idgenerationtest_full_map_to_estates- All land parcels in the map are merged into 3x3 estates- these tests are skipped when running
brownie testdue to long execution time
HighriseLandFundcontract is a temporary contract used for sale purposes. It collects users payments and mints the Land tokens to the users.- Contract States:
ENABLED- contract accepts payments and mints LandDISABLED- contract does not accept payments, owner can enable the contract or withdraw funds
- Entrypoint to the contract from the user perspective is the
fundfunction, which accepts a payload signed with a wallet key on our backend. - When the payload signature is confirmed the payload is unpacked into
tokenId,expiryandcostfor minting purposes. After requirements are met Land NFT is minted to the user FundLandEventis emitted when funding transaction is successful. Pending potential removal - not required anymore since we can track ERC721Transferevents directly.- Contract is granted
MINTER_ROLEforHighriseLand
- Install
ganache- https://trufflesuite.com/ganache/ - Install
brownie(pipxis also required to install it)# `pipx` install python3 -m pip install --user pipx python3 -m pipx ensurepath # install `brownie` with `pipx` pipx install eth-brownie
- Setup
.envfile and include the following variablesDEV_ACCOUNT_NAME- account stored inbrownieused for deploying to testnetsWEB3_INFURA_PROJECT_ID- gateway to blockchain development - set up your account here https://infura.io/ETHERSCAN_TOKEN- create account on https://etherscan.io/ - used for verifying and publishing smart contractsENVIRONMENT_NAME- Highrise environment that contracts will be used on
brownie init- initializes the project and creates project structurebrownie compile- compiles all contracts withincontracts/brownie run <script>- runs custom python scriptbrownie test- runs testsbrownie accounts list- lists all stored accountsbrownie accounts new <account-name>- import existing account via private key. Stored accounts are in encrypted JSON files known askeystoresbrownie networks list- list all available networks to connectbrownie networks add- add new network
- Why to emit events
- There are two types of Solidity event parameters: indexed and not indexed,
- Events are used for return values from the transaction and as a cheap data storage,
- Blockchain keeps event parameters in transaction logsEvents can be filtered by name and by contract address