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
Merged
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"
}
1 change: 1 addition & 0 deletions contracts/src/common/registry/AddressRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pragma solidity =0.8.9;

import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "../../../interface/IAddressRegistry.sol";
import "../../property/Property.sol";

/**
* A registry contract to hold the latest contract addresses.
Expand Down
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
2 changes: 1 addition & 1 deletion test/lockup/lockup-s-token-scenario.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ contract('LockupTest', ([deployer, user1, user2, user3]) => {
let dev: DevProtocolInstance
let property: PropertyInstance
let calc: Calculator
const timestamps: Map<string, number> = new Map()
const timestamps = new Map<string, number>()

const alice = deployer
const bob = user1
Expand Down
5 changes: 5 additions & 0 deletions test/property/property-factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ contract('PropertyFactoryTest', ([deployer, user, user2, marketFactory]) => {
await dev.generateSTokensManager()
await Promise.all([
dev.generateMetricsFactory(),
dev.generateProperty(),
dev.generatePropertyFactory(),
dev.generatePolicyFactory(),
dev.generateLockup(),
Expand All @@ -28,6 +29,7 @@ contract('PropertyFactoryTest', ([deployer, user, user2, marketFactory]) => {
await dev.setCapSetter()
await dev.updateCap()
await dev.addressRegistry.setRegistry('MarketFactory', marketFactory)
await dev.generateProperty()
const propertyAddress = await dev.propertyFactory
.create('sample', 'SAMPLE', user, {
from: user2,
Expand Down Expand Up @@ -92,6 +94,7 @@ contract('PropertyFactoryTest', ([deployer, user, user2, marketFactory]) => {
dev.generateMarketFactory(),
dev.generateMetricsFactory(),
dev.generatePolicyFactory(),
dev.generateProperty(),
dev.generatePropertyFactory(),
dev.generateLockup(),
dev.generateWithdraw(),
Expand Down Expand Up @@ -142,6 +145,7 @@ contract('PropertyFactoryTest', ([deployer, user, user2, marketFactory]) => {
await dev.generateAddressRegistry()
await Promise.all([
dev.generatePolicyFactory(),
dev.generateProperty(),
dev.generatePropertyFactory(),
])
await dev.generatePolicy('PolicyTest1')
Expand Down Expand Up @@ -204,6 +208,7 @@ contract('PropertyFactoryTest', ([deployer, user, user2, marketFactory]) => {
await dev.generateAddressRegistry()
await Promise.all([
dev.generatePolicyFactory(),
dev.generateProperty(),
dev.generatePropertyFactory(),
])
await dev.generatePolicy('PolicyTest1')
Expand Down
33 changes: 26 additions & 7 deletions test/property/property.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ contract(
await dev.generateTreasury()
await dev.setCapSetter()
await dev.updateCap()
await dev.generateProperty()

return dev
}
Expand All @@ -52,6 +53,7 @@ contract(

describe('Property; getBalances', () => {
it('author and treasury hold the balance.', async () => {
await dev.generateProperty()
await dev.generatePropertyFactory()
const transaction = await dev.propertyFactory.create(
'sample',
Expand All @@ -71,6 +73,7 @@ contract(
)
})
it('The balance will be transferred(transfer).', async () => {
await dev.generateProperty()
await dev.generatePropertyFactory()
await dev.generateWithdraw()
const transaction = await dev.propertyFactory.create(
Expand Down Expand Up @@ -98,6 +101,7 @@ contract(
)
})
it('The balance will be transferred(transferFrom).', async () => {
await dev.generateProperty()
await dev.generatePropertyFactory()
await dev.generateWithdraw()
const transaction = await dev.propertyFactory.create(
Expand Down Expand Up @@ -133,19 +137,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 @@ -182,7 +190,8 @@ contract(
'PropertyFactory',
propertyFactory
)
const propertyInstance = await propertyContract.new(
const propertyInstance = await propertyContract.new()
await propertyInstance.initialize(
dev.addressRegistry.address,
author,
'sample',
Expand All @@ -197,6 +206,7 @@ contract(
validateErrorMessage(result, 'illegal sender')
})
it('Change the name', async () => {
await dev.generateProperty()
await dev.generatePropertyFactory()
const transaction = await dev.propertyFactory.create(
'sample',
Expand All @@ -212,12 +222,14 @@ contract(
expect(await propertyInstance.name()).to.be.equal('next-name')
})
it('Should emit ChangeName event', async () => {
await dev.generateProperty()
await dev.generatePropertyFactory()
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 All @@ -241,7 +253,8 @@ contract(
'PropertyFactory',
propertyFactory
)
const propertyInstance = await propertyContract.new(
const propertyInstance = await propertyContract.new()
await propertyInstance.initialize(
dev.addressRegistry.address,
author,
'sample',
Expand All @@ -256,6 +269,7 @@ contract(
validateErrorMessage(result, 'illegal sender')
})
it('Change the symbol', async () => {
await dev.generateProperty()
await dev.generatePropertyFactory()
const transaction = await dev.propertyFactory.create(
'sample',
Expand All @@ -271,12 +285,14 @@ contract(
expect(await propertyInstance.symbol()).to.be.equal('NEXTSYMBOL')
})
it('Should emit ChangeSymbol event', async () => {
await dev.generateProperty()
await dev.generatePropertyFactory()
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 All @@ -303,6 +319,7 @@ contract(
await dev.generateDevBridge()
await dev.generateSTokensManager()
await Promise.all([
dev.generateProperty(),
dev.generatePropertyFactory(),
dev.generatePolicyFactory(),
dev.generateLockup(),
Expand Down Expand Up @@ -354,6 +371,7 @@ contract(
await dev.generateSTokensManager()
await Promise.all([
dev.generateWithdraw(),
dev.generateProperty(),
dev.generatePropertyFactory(),
dev.generateLockup(),
dev.generatePolicyFactory(),
Expand Down Expand Up @@ -404,6 +422,7 @@ contract(
await dev.generateSTokensManager()
await Promise.all([
dev.generateWithdraw(),
dev.generateProperty(),
dev.generatePropertyFactory(),
dev.generateLockup(),
dev.generatePolicyFactory(),
Expand Down
12 changes: 12 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 {
ArbSysTestInstance,
DevPolygonInstance,
TokenURIDescriptorTestInstance,
PropertyInstance,
} from '../../types/truffle-contracts'

type ContractInstance = {
Expand Down Expand Up @@ -56,6 +57,7 @@ export class DevProtocolInstance {
private _devL2!: DevArbitrumInstance | DevPolygonInstance
private _arbSys!: ArbSysTestInstance
private _lockup!: LockupInstance
private _property!: PropertyInstance
private _propertyFactory!: PropertyFactoryInstance
private _policyFactory!: PolicyFactoryTestInstance
private _marketFactory!: MarketFactoryTestInstance
Expand Down Expand Up @@ -246,6 +248,16 @@ export class DevProtocolInstance {
)
}

public async generateProperty(): Promise<void> {
const [proxfied] = await deployProxy(contract('Property'), this._deployer)
this._property = proxfied
await this.addressRegistry.setRegistry(
'Property',
this._property.address,
this.fromDeployer
)
}

public async generatePropertyFactory(): Promise<void> {
const [proxfied] = await deployProxy(
contract('PropertyFactory'),
Expand Down
2 changes: 1 addition & 1 deletion test/withdraw/withdraw-scenario.ts
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ contract('WithdrawTest', ([deployer, user1, user2, user3, user4]) => {
describe('Withdraw; Alice has sent 10% tokens to Bob after 20% tokens sent. Bob has increased from 20% tokens to 30% tokens.', () => {
let dev: DevProtocolInstance
let property: PropertyInstance
const timestamps: Map<string, number> = new Map()
const timestamps = new Map<string, number>()
const alice = deployer
const bob = user1
const TRANSFERD_PROPERTY_TOKEN_PERCENT = 10
Expand Down