Create contracts from other contracts #197

Closed
opened 2019-12-09 21:30:05 +09:00 by zxq9 · 12 comments
zxq9 commented 2019-12-09 21:30:05 +09:00 (Migrated from gitlab.com)

Created by: UlfNorell

From the Sophia discussion at the Sofia workshop.

*Created by: UlfNorell* *From the Sophia discussion at the Sofia workshop.*
zxq9 commented 2019-12-09 21:32:12 +09:00 (Migrated from gitlab.com)

Created by: UlfNorell

Possible design: Include source code of child contract. Compiler compiles it to a byte code literal that can be deployed with a new CREATE_CONTRACT instruction. From Sophia:

  let c = Contract.create(init_args, amount = amount) : ChildContract
  c.foo_bar()
*Created by: UlfNorell* Possible design: Include source code of child contract. Compiler compiles it to a byte code literal that can be deployed with a new `CREATE_CONTRACT` instruction. From Sophia: ```sophia let c = Contract.create(init_args, amount = amount) : ChildContract c.foo_bar() ```
zxq9 commented 2019-12-11 08:39:51 +09:00 (Migrated from gitlab.com)

Created by: nikita-fuchs

I havn't seen anything besides DAOs using this feature, also because this sort of thing is quite pricey. Although I was the one initially pushing for it some time ago, I wouldn't delay something more important as, say, native tokens for this.

*Created by: nikita-fuchs* I havn't seen anything besides DAOs using this feature, also because this sort of thing is quite pricey. Although I was the one initially pushing for it some time ago, I wouldn't delay something more important as, say, native tokens for this.
zxq9 commented 2019-12-11 15:24:08 +09:00 (Migrated from gitlab.com)

Created by: UlfNorell

Native tokens is a massive undertaking that isn't really affected one way or the other by how we prioritise Sophia development.

*Created by: UlfNorell* Native tokens is a massive undertaking that isn't really affected one way or the other by how we prioritise Sophia development.
zxq9 commented 2019-12-11 19:51:51 +09:00 (Migrated from gitlab.com)

Created by: evdoks

@UlfNorell I think Nikita is talking about resources that we can either allocate to further work on Sophia or to start working on Native Tokens. I assume that you mean is that there are no dependencies between those two.

PS 'resources' = @hanssv 🙄

*Created by: evdoks* @UlfNorell I think Nikita is talking about resources that we can either allocate to further work on Sophia or to start working on Native Tokens. I assume that you mean is that there are no dependencies between those two. PS 'resources' = @hanssv 🙄
zxq9 commented 2019-12-11 19:54:51 +09:00 (Migrated from gitlab.com)

Created by: UlfNorell

No, I'm saying the effort required for native tokens is vastly higher than for any of the current Sophia extension proposals, so it makes no sense to pit them against each other.

*Created by: UlfNorell* No, I'm saying the effort required for native tokens is vastly higher than for any of the current Sophia extension proposals, so it makes no sense to pit them against each other.
zxq9 commented 2019-12-11 22:02:10 +09:00 (Migrated from gitlab.com)

Created by: nikita-fuchs

Well I think it does, if the smaller effort would slow down the bigger one significantly? I mean, you guys know best. I just think that prioritizing the native tokens would make sense.

*Created by: nikita-fuchs* Well I think it does, if the smaller effort would slow down the bigger one significantly? I mean, you guys know best. I just think that prioritizing the native tokens would make sense.
zxq9 commented 2020-12-02 19:31:20 +09:00 (Migrated from gitlab.com)

Created by: radrow

This should go live now.

Main usecases

  • Fungible tokens factories. Will ease the process of creation and will vanish lots of security doubts (no need to validate the code each time)
  • On chain management of hyperchains staking contract. Factories will allow to redefine the staking contract in a more flexible and modularized way
  • Governance app factory. You will no longer need to deploy any contracts manually
*Created by: radrow* This should go live now. ## Main usecases - Fungible tokens factories. Will ease the process of creation and will vanish lots of security doubts (no need to validate the code each time) - On chain management of hyperchains staking contract. Factories will allow to redefine the staking contract in a more flexible and modularized way - Governance app factory. You will no longer need to deploy any contracts manually
zxq9 commented 2020-12-02 21:38:46 +09:00 (Migrated from gitlab.com)

Created by: UlfNorell

Can you elaborate on each of these cases, explaining for instance, when and by whom the byte code for the new contracts is produced, and what checks are required? Also, what are the concrete advantages over manual contract deployment?

In the first case (if I understand it correctly), the fungible-token contract is fixed, so it can be compiled and shipped together with the factory contract. No checks other than obvious run-time checks that the create contract transaction is well-formed are required.

I don't see how using the factory is any easier than manual deployment. Both cases involve creating a transaction with some data for the init function.

Regarding security concerns, it's not clear to me that there is a huge gain.

Manual deployment

  • Deployer: needs to verify that the correct contract is being deployed (but this could be as simple as checking the hash of the byte code)
  • User: match the on-chain byte code against provided source code

Automatic deployment

  • Deployer: check that you are calling the correct factory (can be verified once, and then simply check the address)
  • User: look up the transaction that created the contract and see that it's from a trusted factory (can this be done easily?)
*Created by: UlfNorell* Can you elaborate on each of these cases, explaining for instance, when and by whom the byte code for the new contracts is produced, and what checks are required? Also, what are the concrete advantages over manual contract deployment? In the first case (if I understand it correctly), the fungible-token contract is fixed, so it can be compiled and shipped together with the factory contract. No checks other than obvious run-time checks that the create contract transaction is well-formed are required. I don't see how using the factory is any easier than manual deployment. Both cases involve creating a transaction with some data for the init function. Regarding security concerns, it's not clear to me that there is a huge gain. Manual deployment - Deployer: needs to verify that the correct contract is being deployed (but this could be as simple as checking the hash of the byte code) - User: match the on-chain byte code against provided source code Automatic deployment - Deployer: check that you are calling the correct factory (can be verified once, and then simply check the address) - User: look up the transaction that created the contract and see that it's from a trusted factory (can this be done easily?)
zxq9 commented 2021-02-04 03:32:49 +09:00 (Migrated from gitlab.com)

Created by: mradkov

Currently without having this feature UX is a pain.

Example use case:

  • Token Bonding Curve [A]
    • we have a contract which defines the price of a token by a mathematical curve
  • Token Sale [B]
  • Token (AEX9) [C]
    • regular AEX9 token that is being acquired/sold (mint/burn) via the actions buy/sell.
      registering token for sale
  • Furthermore there is a Registry Contract [D] to store an index of all available tokens

Current flow:

  • Step 1: user deploys Contract A - requires signature and confirmation in the wallet
  • Step 2: user deploys Contract B - requires signature and confirmation in the wallet
  • Step 2: user deploys Contract C - requires signature and confirmation in the wallet
  • Step 3: user makes contractCall to link Contract A to Contract B - requires signature and confirmation in the wallet
  • Step 4: user makes contractCall to link Contract B to Contract C - requires signature and confirmation in the wallet.
  • Step 5: user makes contractCall to link Contract C to Contract D - requires signature and confirmation in the wallet.

That is a total of 5 steps with 5 individual confirmations.

How you can do it in Solidity using a single contract deployment:

contract MyToken is ERC20, ERC20Mintable {
    // ... see "Tokens" for more info
}

contract MyCrowdsale is Crowdsale, MintedCrowdsale {
    constructor(
        uint256 rate,    // rate in TKNbits
        address payable wallet,
        IERC20 token
    )
        MintedCrowdsale()
        Crowdsale(rate, wallet, token)
        public
    {

    }
}

contract MyCrowdsaleDeployer {
    constructor()
        public
    {
        // create a mintable token
        ERC20Mintable token = new MyToken();

        // create the crowdsale and tell it about the token
        Crowdsale crowdsale = new MyCrowdsale(
            1,               // rate, still in TKNbits
            msg.sender,      // send Ether to the deployer
            token            // the token
        );
        // transfer the minter role from this contract (the default)
        // to the crowdsale, so it can mint tokens
        token.addMinter(address(crowdsale));
        token.renounceMinter();

        // A BIT MORE LOGIC TO ADD THIS TO THE RELEVANT REGISTRIES

    }
}

Done with single contract deployment - 1 signature required.

*Created by: mradkov* Currently without having this feature UX is a pain. ## Example use case: - `Token Bonding Curve [A]` - we have a contract which defines the price of a token by a mathematical curve - `Token Sale [B]` - `Token (AEX9) [C]` - regular AEX9 token that is being acquired/sold (mint/burn) via the actions buy/sell. registering token for sale - Furthermore there is a `Registry Contract [D]` to store an index of all available tokens ## Current flow: - Step 1: user deploys `Contract A` - requires signature and confirmation in the wallet - Step 2: user deploys `Contract B` - requires signature and confirmation in the wallet - Step 2: user deploys `Contract C` - requires signature and confirmation in the wallet - Step 3: user makes contractCall to link `Contract A` to `Contract B` - requires signature and confirmation in the wallet - Step 4: user makes contractCall to link `Contract B` to `Contract C` - requires signature and confirmation in the wallet. - Step 5: user makes contractCall to link `Contract C` to `Contract D` - requires signature and confirmation in the wallet. That is a total of 5 steps with 5 individual confirmations. ## How you can do it in Solidity using a single contract deployment: ```solidity contract MyToken is ERC20, ERC20Mintable { // ... see "Tokens" for more info } contract MyCrowdsale is Crowdsale, MintedCrowdsale { constructor( uint256 rate, // rate in TKNbits address payable wallet, IERC20 token ) MintedCrowdsale() Crowdsale(rate, wallet, token) public { } } contract MyCrowdsaleDeployer { constructor() public { // create a mintable token ERC20Mintable token = new MyToken(); // create the crowdsale and tell it about the token Crowdsale crowdsale = new MyCrowdsale( 1, // rate, still in TKNbits msg.sender, // send Ether to the deployer token // the token ); // transfer the minter role from this contract (the default) // to the crowdsale, so it can mint tokens token.addMinter(address(crowdsale)); token.renounceMinter(); // A BIT MORE LOGIC TO ADD THIS TO THE RELEVANT REGISTRIES } } ``` Done with single contract deployment - 1 signature required.
gorbak25 commented 2021-02-04 05:29:42 +09:00 (Migrated from gitlab.com)

Currently without having this feature UX is a pain.

Example use case:

* `Token Bonding Curve [A]`
  
  * we have a contract which defines the price of a token by a mathematical curve

* `Token Sale [B]`

* `Token (AEX9) [C]`
  
  * regular AEX9 token that is being acquired/sold (mint/burn) via the actions buy/sell.
    registering token for sale

* Furthermore there is a `Registry Contract [D]` to store an index of all available tokens

Current flow:

* Step 1: user deploys `Contract A` - requires signature and confirmation in the wallet

* Step 2: user deploys `Contract B` - requires signature and confirmation in the wallet

* Step 2: user deploys `Contract C` - requires signature and confirmation in the wallet

* Step 3: user makes contractCall  to link `Contract A` to `Contract B` - requires signature and confirmation in the wallet

* Step 4: user makes contractCall to link `Contract B` to `Contract C`  - requires signature and confirmation in the wallet.

* Step 5: user makes contractCall to link `Contract C` to `Contract D`  - requires signature and confirmation in the wallet.

That is a total of 5 steps with 5 individual confirmations.

How you can do it in Solidity using a single contract deployment:

contract MyToken is ERC20, ERC20Mintable {
    // ... see "Tokens" for more info
}

contract MyCrowdsale is Crowdsale, MintedCrowdsale {
    constructor(
        uint256 rate,    // rate in TKNbits
        address payable wallet,
        IERC20 token
    )
        MintedCrowdsale()
        Crowdsale(rate, wallet, token)
        public
    {

    }
}

contract MyCrowdsaleDeployer {
    constructor()
        public
    {
        // create a mintable token
        ERC20Mintable token = new MyToken();

        // create the crowdsale and tell it about the token
        Crowdsale crowdsale = new MyCrowdsale(
            1,               // rate, still in TKNbits
            msg.sender,      // send Ether to the deployer
            token            // the token
        );
        // transfer the minter role from this contract (the default)
        // to the crowdsale, so it can mint tokens
        token.addMinter(address(crowdsale));
        token.renounceMinter();

        // A BIT MORE LOGIC TO ADD THIS TO THE RELEVANT REGISTRIES

    }
}

Done with single contract deployment - 1 signature required.

No. It's not as simple as that 🙃
As a user you also need to verify the bytecode of each individual contract as without it a raccoon can backdoor each subcontract. So don't forget to validate the bytecode either on the server side or the client side of every contract.
With contract factories you only need ONE contract which can produce the token/bonding curve etc... You only need to validate one contract one time on an external site - like on etherscan.

The same goes for the our governance aepp where some complex centralized validation infrastructure is required in order for it to be somewhat secure.

> Currently without having this feature UX is a pain. > ## Example use case: > > * `Token Bonding Curve [A]` > > * we have a contract which defines the price of a token by a mathematical curve > > * `Token Sale [B]` > > * `Token (AEX9) [C]` > > * regular AEX9 token that is being acquired/sold (mint/burn) via the actions buy/sell. > registering token for sale > > * Furthermore there is a `Registry Contract [D]` to store an index of all available tokens > > > ## Current flow: > > * Step 1: user deploys `Contract A` - requires signature and confirmation in the wallet > > * Step 2: user deploys `Contract B` - requires signature and confirmation in the wallet > > * Step 2: user deploys `Contract C` - requires signature and confirmation in the wallet > > * Step 3: user makes contractCall to link `Contract A` to `Contract B` - requires signature and confirmation in the wallet > > * Step 4: user makes contractCall to link `Contract B` to `Contract C` - requires signature and confirmation in the wallet. > > * Step 5: user makes contractCall to link `Contract C` to `Contract D` - requires signature and confirmation in the wallet. > > > That is a total of 5 steps with 5 individual confirmations. > ## How you can do it in Solidity using a single contract deployment: > > ```solidity > contract MyToken is ERC20, ERC20Mintable { > // ... see "Tokens" for more info > } > > contract MyCrowdsale is Crowdsale, MintedCrowdsale { > constructor( > uint256 rate, // rate in TKNbits > address payable wallet, > IERC20 token > ) > MintedCrowdsale() > Crowdsale(rate, wallet, token) > public > { > > } > } > > contract MyCrowdsaleDeployer { > constructor() > public > { > // create a mintable token > ERC20Mintable token = new MyToken(); > > // create the crowdsale and tell it about the token > Crowdsale crowdsale = new MyCrowdsale( > 1, // rate, still in TKNbits > msg.sender, // send Ether to the deployer > token // the token > ); > // transfer the minter role from this contract (the default) > // to the crowdsale, so it can mint tokens > token.addMinter(address(crowdsale)); > token.renounceMinter(); > > // A BIT MORE LOGIC TO ADD THIS TO THE RELEVANT REGISTRIES > > } > } > ``` > > Done with single contract deployment - 1 signature required. No. It's not as simple as that :upside_down_face: As a user you also need to verify the bytecode of each individual contract as without it a raccoon can backdoor each subcontract. So don't forget to validate the bytecode either on the server side or the client side of every contract. With contract factories you only need ONE contract which can produce the token/bonding curve etc... You only need to validate one contract one time on an external site - like on etherscan. The same goes for the our governance aepp where some complex centralized validation infrastructure is required in order for it to be somewhat secure.
gorbak25 commented 2021-02-04 05:50:37 +09:00 (Migrated from gitlab.com)

Can you elaborate on each of these cases, explaining for instance, when and by whom the byte code for the new contracts is produced, and what checks are required? Also, what are the concrete advantages over manual contract deployment?

In the first case (if I understand it correctly), the fungible-token contract is fixed, so it can be compiled and shipped together with the factory contract. No checks other than obvious run-time checks that the create contract transaction is well-formed are required.

I don't see how using the factory is any easier than manual deployment. Both cases involve creating a transaction with some data for the init function.

Regarding security concerns, it's not clear to me that there is a huge gain.

Manual deployment

* Deployer: needs to verify that the correct contract is being deployed (but this could be as simple as checking the hash of the byte code)

* User: match the on-chain byte code against provided source code

Automatic deployment

* Deployer: check that you are calling the correct factory (can be verified once, and then simply check the address)

* User: look up the transaction that created the contract and see that it's from a trusted factory (can this be done easily?)

Consider a gaming platform where people are playing tick-tack-toe for money. Each game is coordinated by a contract factory which deploys new tick-tack-toe games and tracks their status. When someone wants to play, the contract factory automatically either deploys a new contract with the game or assigns you to an existing game. The lifecycle of each game is:

WaitingForChallenger -> Game -> Done

Let's say Alice wants to play against Bob:

1. Alice calls the factory and a new game gets created - she gets an address C
2. Bob calls the factory and gets assigned to Alice - he gets C
3. Alice and Bob play using C
4. After the game is done C calls the factory to deregister itself

Does Alice or Bob need to validate that C was deployed by the Factory? Of course not - If the only way for a contract to get registered in the factory is by being deployed by the factory itself then we know what C is by validating the factory.
Essentially when a contract factory tracks contracts deployed by itself then by validating the factory we can ensure that any deployed subcontracts were not being manipulated by someone.

> Can you elaborate on each of these cases, explaining for instance, when and by whom the byte code for the new contracts is produced, and what checks are required? Also, what are the concrete advantages over manual contract deployment? > > In the first case (if I understand it correctly), the fungible-token contract is fixed, so it can be compiled and shipped together with the factory contract. No checks other than obvious run-time checks that the create contract transaction is well-formed are required. > > I don't see how using the factory is any easier than manual deployment. Both cases involve creating a transaction with some data for the init function. > > Regarding security concerns, it's not clear to me that there is a huge gain. > > Manual deployment > > * Deployer: needs to verify that the correct contract is being deployed (but this could be as simple as checking the hash of the byte code) > > * User: match the on-chain byte code against provided source code > > > Automatic deployment > > * Deployer: check that you are calling the correct factory (can be verified once, and then simply check the address) > > * User: look up the transaction that created the contract and see that it's from a trusted factory (can this be done easily?) Consider a gaming platform where people are playing tick-tack-toe for money. Each game is coordinated by a contract factory which deploys new tick-tack-toe games and tracks their status. When someone wants to play, the contract factory automatically either deploys a new contract with the game or assigns you to an existing game. The lifecycle of each game is: ``` WaitingForChallenger -> Game -> Done ``` Let's say Alice wants to play against Bob: ``` 1. Alice calls the factory and a new game gets created - she gets an address C 2. Bob calls the factory and gets assigned to Alice - he gets C 3. Alice and Bob play using C 4. After the game is done C calls the factory to deregister itself ``` Does Alice or Bob need to validate that C was deployed by the Factory? Of course not - If the only way for a contract to get registered in the factory is by being deployed by the factory itself then we know what C is by validating the factory. Essentially when a contract factory tracks contracts deployed by itself then by validating the factory we can ensure that any deployed subcontracts were not being manipulated by someone.
gorbak25 commented 2021-02-14 08:00:02 +09:00 (Migrated from gitlab.com)

@UlfNorell Could you give us a time estimate for this task?

@UlfNorell Could you give us a time estimate for this task?
Sign in to join this conversation.
No Milestone
No project
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: QPQ-AG/sophia#197
No description provided.