Skip to content

Commit

Permalink
doc: added README for land-sale package
Browse files Browse the repository at this point in the history
  • Loading branch information
capedcrusader21 committed Nov 21, 2024
1 parent 154fc72 commit 7a58b85
Show file tree
Hide file tree
Showing 6 changed files with 290 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import {DeployFunction} from 'hardhat-deploy/types';
import {HardhatRuntimeEnvironment} from 'hardhat/types';

const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
const {deployments, getNamedAccounts} = hre;
const {deploy} = deployments;
const {deployer, sandAdmin, backendAuthWallet} = await getNamedAccounts();
await deploy('PolygonAuthValidator', {
contract: 'AuthValidator',
from: deployer,
args: [sandAdmin, backendAuthWallet],
log: true,
skipIfAlreadyDeployed: true,
});
};
export default func;
func.tags = ['PolygonAuthValidator', 'PolygonAuthValidator_deploy'];
139 changes: 139 additions & 0 deletions packages/deploy/deploy/1000_landsale/02_deploy_estate_sale.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
import {Deployment} from 'hardhat-deploy/dist/types';
import {DeployFunction} from 'hardhat-deploy/types';
import {HardhatRuntimeEnvironment} from 'hardhat/types';
import {
getDeadline,
getLandSales,
LandSale,
setAsLandMinter,
writeProofs,
} from '../../../core/data/landSales/getLandSales';
import {skipUnlessTest} from '../../../core/utils/network';

type SaleDeployment = {
name: string;
// top level skip function for the whole sale data
skip?: (env: HardhatRuntimeEnvironment) => Promise<boolean>;
// object map of skip function for each individual sector
skipSector?: {
[sector: number]: (env: HardhatRuntimeEnvironment) => Promise<boolean>;
};
};

const sales: SaleDeployment[] = [
{name: 'EstateSaleWithAuth_0', skip: skipUnlessTest},
{name: 'LandPreSale_19', skip: async () => true},
{name: 'LandPreSale_20', skip: async () => true},
{name: 'LandPreSale_21', skip: async () => true},
{name: 'LandPreSale_22', skip: async () => true},
{name: 'LandPreSale_23', skip: async () => true},
{name: 'LandPreSale_24', skip: async () => true},
{name: 'LandPreSale_25', skip: async () => true},
{name: 'LandPreSale_26', skip: async () => true},
{name: 'LandPreSale_27', skip: async () => true},
{name: 'LandPreSale_28', skip: async () => true},
{name: 'LandPreSale_29', skip: async () => true},
{name: 'LandPreSale_30', skip: async () => true},
{name: 'LandPreSale_31', skip: async () => true},
{name: 'LandPreSale_32', skip: async () => true},
{name: 'LandPreSale_33', skip: async () => true},
{name: 'LandPreSale_34', skip: async () => true},
{name: 'LandPreSale_35', skip: async () => true},
{name: 'LandPreSale_36', skip: async () => true},
{name: 'LandPreSale_37', skip: async () => true},
];

const func: DeployFunction = async function (hre) {
const {deployments, getNamedAccounts} = hre;
const {deploy} = deployments;
const {
deployer,
landSaleBeneficiary,
backendReferralWallet,
landSaleFeeRecipient,
landSaleAdmin,
assetAdmin,
} = await getNamedAccounts();
const sandContract = await deployments.get('PolygonSand');
const landContract = await deployments.get('PolygonLand');
let assetContract: Deployment;
const deployedAsset = await deployments.getOrNull('Asset'); // L2 Asset, json files available on Polygon and Mumbai
if (!deployedAsset) {
// mock asset used for test networks and forking
// TODO: change to MockAsset from packages/asset when outside core
assetContract = await deploy('MockERC1155Asset', {
from: assetAdmin,
args: ['http://nft-test/nft-1155-{id}'],
log: true,
skipIfAlreadyDeployed: true,
});
} else {
assetContract = deployedAsset;
}
const authValidatorContract = await deployments.get('PolygonAuthValidator');

async function deployLandSale(name: string, landSale: LandSale) {
const {lands, merkleRootHash, sector} = landSale;
const landSaleName = `${name}_${sector}`;
const deadline = getDeadline(hre, sector);
const deployName = `PolygonLandPreSale_${sector}`;
let landSaleDeployment = await deployments.getOrNull(deployName);
if (!landSaleDeployment) {
landSaleDeployment = await deploy(deployName, {
from: deployer,
linkedData: lands,
contract: 'EstateSaleWithAuth',
args: [
landContract.address,
sandContract.address,
sandContract.address,
landSaleAdmin,
landSaleBeneficiary,
merkleRootHash,
deadline,
backendReferralWallet,
2000,
'0x0000000000000000000000000000000000000000',
assetContract.address,
landSaleFeeRecipient,
authValidatorContract.address,
],
log: true,
});
writeProofs(hre, landSaleName, landSale);
}
await setAsLandMinter(hre, landSaleDeployment.address, 'PolygonLand');
}

for (const sale of sales) {
if (sale.skip) {
const skip = await sale.skip(hre);
if (skip) continue;
}
const landSales = await getLandSales(
sale.name,
hre.network.name,
hre.network.live
);
const skipSector = sale.skipSector || {};
const sectors = Object.keys(skipSector).map((k) => parseInt(k));
for (const landSale of landSales) {
if (sectors.includes(landSale.sector)) {
const skip = await skipSector[landSale.sector](hre);
if (skip) {
console.log(`Skipping sector ${landSale.sector}`);
continue;
}
}
await deployLandSale(sale.name, landSale);
}
}
};

export default func;
func.tags = ['PolygonEstateSaleWithAuth', 'PolygonEstateSaleWithAuth_deploy'];
func.dependencies = [
'PolygonSand_deploy',
'PolygonLand_deploy',
'PolygonAuthValidator_deploy',
];
8 changes: 7 additions & 1 deletion packages/land-sale/.solcover.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,11 @@ module.exports = {
grep: '@skip-on-coverage', // Find everything with this tag
invert: true, // Run the grep's inverse set.
},
skipFiles: ['/mock'],
skipFiles: [
'/mocks',
'/AuthValidator.sol',
'common/BaseWithStorage',
'common/Libraries/SafeMathWithRequire.sol',
'ReferralValidator/ReferralValidator.sol',
],
};
110 changes: 110 additions & 0 deletions packages/land-sale/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
# land-sale

The land-sale package outlines the process for deploying Land Presale
smartcontracts for The Sandbox's metaverse.

## Architecture

This package manages deployments for Land sales. The package contains 2 main
contracts:

| Component | Description |
| ------------------------------------------------------ | ---------------------------------------------------------------------------------- |
| [AuthValidator](contracts/AuthValidator.sol) | contract which verifies that only a trusted wallet can authorize land sale actions |
| [EstateSaleWithAuth](contracts/EstateSaleWithAuth.sol) | contract used to create and manage land sales in the metaverse. |

- It leverages two key files:
- **bundles.testnet.json**: Specifies optional asset bundles sold with certain
Lands.
- **sectors.testnet.json**: Defines the sectors being deployed. Deploy a new
Land Presale contract for each sector using the `EstateSaleWithAuth` template,
as shown in the deploy script.
- **No need for new deploy scripts**: Instead of creating a new deploy script
for each sale, the existing script is updated with the newsectors.
- **Set a Deadline**: A deadline must be specified in
`packages/core/data/landSales/data/deadlines.ts`.
- For mainnet deadline will be of six months and for testnet this deadline is
ignored by the script.

## Getting Started

### Step 1: Prepare for Deployment

- **Receive JSON Files**: The Landsale team will provide `bundles.testnet.json`
and `sectors.testnet.json` files.
- **Organize the Files**: Place the JSON files in a new folder within
`packages/core/data/landSales` named `LandPreSale_XX`.
- **NOTE**: Here, `XX` is an incremented folder number that does not correspond
to sector numbers.

### Step 2: Manage Secrets

- For testnet, the secret file is automatically generated in the deploy folder.
- For mainnet, you must manually create a file at
`packages/deploy/secrets/estate-sale/.LandPreSale_XX_testnet_secret`, where XX
is the sector number, and note that the mainnet secret differs from the
testnet secret.

---

## Sample files

### bundles.test.json :

```
{
"bundleId":
[
bundle-Id
]
}
```

### sectors.testnet.json :

```
[
{
"sector": sector_number,
"lands": [
{
"coordinateX": X-coordinate,
"coordinateY": Y-coordinate,
"ownerAddress": "",
"bundleId": bundle-Id
}
]
}
]
```

### deadlines.ts :

- The deadline represents the timestamp (in seconds) until which the land sale
contract for each sector will remain active, with the deadline number
corresponding to the sector number.
- Place the deadline in `packages/core/data/landSales/data/deadlines.ts`

```
sector_number: new Date('YYYY-MM-DDT12:00:00.000Z').valueOf() / 1000
```

---

## Running the project locally

- Make sure you navigate to the `deploy` package directory before running any
commands
- Create a new `.env` file by copying the structure from `.env.example`
- Ensure you replace any placeholder values with the actual configuration needed
for your environment.
- Install dependencies with `yarn`

To execute the deployment, run

- for fork deployment:
`yarn fork:deploy --network NETWORK --tags TAG --no-impersonation`
- for live deployment: `yarn live:deploy --network NETWORK --tags TAG`
- where:
- `NETWORK` is the network name like: `polygon`, `mainet` etc
- `TAG` are the tags used to limit which deployment scripts will be executed
Loading

1 comment on commit 7a58b85

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverage for this commit

90.32%

Coverage Report
FileStmtsBranchesFuncsLinesUncovered Lines
packages/land-sale/contracts
   EstateSaleWithAuth.sol80.33%68.18%75%90.32%109, 125, 166, 166, 169, 259–266, 63, 74, 80, 88, 88, 88–89
packages/land-sale/contracts/common/Interfaces
   ERC1155.sol100%100%100%100%
   ERC165.sol100%100%100%100%
   ERC20.sol100%100%100%100%
   ERC20WithMetadata.sol100%100%100%100%
   ERC721.sol100%100%100%100%
   ERC721Events.sol100%100%100%100%
   ILandToken.sol100%100%100%100%

Please sign in to comment.