Skip to content

use clone in property factory #408

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Feb 1, 2023
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@
],
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
}
},
"solidity.compileUsingRemoteVersion": "v0.8.9+commit.e5eed63a"
}
12 changes: 8 additions & 4 deletions contracts/src/property/Property.sol
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
// SPDX-License-Identifier: MPL-2.0
pragma solidity =0.8.9;

import "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
import "../../interface/IWithdraw.sol";
import "../../interface/IProperty.sol";
import "../../interface/IPropertyFactory.sol";
import "../../interface/IPolicy.sol";
import "../common/registry/UsingRegistry.sol";
import "../common/registry/InitializableUsingRegistry.sol";

/**
* A contract that represents the assets of the user and collects staking from the stakers.
* Property contract inherits ERC20.
* Holders of Property contracts(tokens) receive holder rewards according to their share.
*/
contract Property is ERC20, UsingRegistry, IProperty {
contract Property is ERC20Upgradeable, InitializableUsingRegistry, IProperty {
uint8 private constant PROPERTY_DECIMALS = 18;
uint8 private __decimals;
uint256 private constant SUPPLY = 10000000000000000000000000;
Expand All @@ -32,12 +33,15 @@ contract Property is ERC20, UsingRegistry, IProperty {
* @param _name The name of the new Property.
* @param _symbol The symbol of the new Property.
*/
constructor(
function initialize(
address _registry,
address _own,
string memory _name,
string memory _symbol
) ERC20(_name, _symbol) UsingRegistry(_registry) {
) public initializer {
__ERC20_init(_name, _symbol);
__UsingRegistry_init(_registry);

/**
* Validates the sender is PropertyFactory contract.
*/
Expand Down
5 changes: 3 additions & 2 deletions contracts/src/property/PropertyFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import "../../interface/IPropertyFactory.sol";
import "../../interface/IMarket.sol";
import "../common/registry/InitializableUsingRegistry.sol";
import "./Property.sol";
import "@openzeppelin/contracts/proxy/Clones.sol";

/**
* A factory contract that creates a new Property contract.
Expand Down Expand Up @@ -77,13 +78,13 @@ contract PropertyFactory is InitializableUsingRegistry, IPropertyFactory {
/**
* Creates a new Property contract.
*/
Property _property = new Property(
address propertyAddr = Clones.clone(registry().registries("Property"));
Property(propertyAddr).initialize(
address(registry()),
_author,
_name,
_symbol
);
address propertyAddr = address(_property);

/**
* Adds the new Property contract to the Property address set.
Expand Down
49 changes: 49 additions & 0 deletions migrations/update/1_update-property-factory-with-seed-property.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { upgradeProxy, validateUpgrade } from '@openzeppelin/truffle-upgrades'
import { type ContractClass } from '@openzeppelin/truffle-upgrades/dist/utils'

const PropertyFactory = artifacts.require('PropertyFactory')
const AddressRegistry = artifacts.require('AddressRegistry')

const handler = async function (_, network) {
if (network === 'test') {
return
}

const proxyAddress = process.env.PROPERTY_FACTORY_PROXY!
const proxyAddressAddressRegistry = process.env.ADDRESS_REGISTRY_PROXY!

const newProperty = artifacts.require('Property')
_.deploy(newProperty)
const deployedNewProperty = await newProperty.deployed()
console.log(`[CONFIRMED] new seed Property: ${deployedNewProperty.address}`)

const existingAddressRegistry = await AddressRegistry.deployed().catch(() =>
AddressRegistry.at(proxyAddressAddressRegistry)
)

await existingAddressRegistry.setRegistry(
'Property',
deployedNewProperty.address
)
console.log('[CONFIRMED] set the seed Property to Registry')

const existing = await PropertyFactory.deployed().catch(() =>
PropertyFactory.at(proxyAddress)
)

console.log('proxy:', existing.address)

await validateUpgrade(
existing.address,
PropertyFactory as unknown as ContractClass
)

console.log('New implementation is valid')

await upgradeProxy(
existing.address,
PropertyFactory as unknown as ContractClass
)
} as Truffle.Migration

export = handler
22 changes: 15 additions & 7 deletions test/property/property.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,19 +130,23 @@ contract(

describe('Property; constructor', () => {
it('Cannot be created from other than factory', async () => {
const result = await propertyContract
.new(dev.addressRegistry.address, author, 'sample', 'SAMPLE', {
const propertyInstance = await propertyContract.new()

const result = await propertyInstance
.initialize(dev.addressRegistry.address, author, 'sample', 'SAMPLE', {
from: deployer,
})
.catch((err: Error) => err)

validateAddressErrorMessage(result)
})
it('The author, decimal places, and number of issues are fixed values', async () => {
await dev.addressRegistry.setRegistry(
'PropertyFactory',
propertyFactory
)
const propertyInstance = await propertyContract.new(
const propertyInstance = await propertyContract.new()
await propertyInstance.initialize(
dev.addressRegistry.address,
author,
'sample',
Expand Down Expand Up @@ -179,7 +183,8 @@ contract(
'PropertyFactory',
propertyFactory
)
const propertyInstance = await propertyContract.new(
const propertyInstance = await propertyContract.new()
await propertyInstance.initialize(
dev.addressRegistry.address,
author,
'sample',
Expand Down Expand Up @@ -214,7 +219,8 @@ contract(
'PropertyFactory',
propertyFactory
)
const propertyInstance = await propertyContract.new(
const propertyInstance = await propertyContract.new()
await propertyInstance.initialize(
dev.addressRegistry.address,
author,
'sample',
Expand All @@ -238,7 +244,8 @@ contract(
'PropertyFactory',
propertyFactory
)
const propertyInstance = await propertyContract.new(
const propertyInstance = await propertyContract.new()
await propertyInstance.initialize(
dev.addressRegistry.address,
author,
'sample',
Expand Down Expand Up @@ -273,7 +280,8 @@ contract(
'PropertyFactory',
propertyFactory
)
const propertyInstance = await propertyContract.new(
const propertyInstance = await propertyContract.new()
await propertyInstance.initialize(
dev.addressRegistry.address,
author,
'sample',
Expand Down
14 changes: 14 additions & 0 deletions test/test-lib/instance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import type {
ArbSysTestInstance,
DevPolygonInstance,
TokenURIDescriptorTestInstance,
PropertyInstance,
TokenURIDescriptorCopyTestInstance,
TokenURIDescriptorLegacyTestInstance,
} from '../../types/truffle-contracts'
Expand Down Expand Up @@ -248,7 +249,20 @@ export class DevProtocolInstance {
)
}

public async generateProperty(): Promise<void> {
const Property = contract('Property')
const property = await Property.new(this.fromDeployer)

await this.addressRegistry.setRegistry(
'Property',
property.address,
this.fromDeployer
)
}

public async generatePropertyFactory(): Promise<void> {
await this.generateProperty()

const [proxfied] = await deployProxy(
contract('PropertyFactory'),
this._deployer
Expand Down