Contract Factories












4















Has there been any research into how a contract factory might be made in Michelson/Liquidity?



To elaborate, in Solidity a contract factory might look like:



pragma solidity ^0.4.8;

contract Bakery {

// index of created contracts

address public contracts;

// useful to know the row count in contracts index

function getContractCount()
public
constant
returns(uint contractCount)
{
return contracts.length;
}

// deploy a new contract

function newCookie()
public
returns(address newContract)
{
Cookie c = new Cookie();
contracts.push(c);
return c;
}
}


contract Cookie {

// suppose the deployed contract has a purpose

function getFlavor()
public
constant
returns (string flavor)
{
return "mmm ... chocolate chip";
}
}


(referenced from https://ethereum.stackexchange.com/questions/13415/deploy-contract-from-contract-in-solidity)



This is a powerful feature in DAPP development, as it allows you to build an object oriented structure for your DAPP where requests can create new contracts. It is a well established design pattern, so what would the equivalent be in the Tezos ecosystem?










share|improve this question























  • It appears like CREATE_CONTRACT { storage 'g ; parameter 'p ; code ... } would work, but this will bloat the size of a contract a bit, and it feels like there should be a way to handle this gracefully like in Solidity's Java style class instantiation.

    – Rob
    Mar 11 at 23:54











  • If not, a clean example in Michelson would be nice.

    – Rob
    Mar 11 at 23:56













  • ok cool, probably a ways out then.

    – Rob
    Mar 12 at 0:24






  • 1





    I put a comment that I deleted to convert it into an answer. I missed your comment that was added afterwards. My apologies for this.

    – FFF
    Mar 12 at 0:34
















4















Has there been any research into how a contract factory might be made in Michelson/Liquidity?



To elaborate, in Solidity a contract factory might look like:



pragma solidity ^0.4.8;

contract Bakery {

// index of created contracts

address public contracts;

// useful to know the row count in contracts index

function getContractCount()
public
constant
returns(uint contractCount)
{
return contracts.length;
}

// deploy a new contract

function newCookie()
public
returns(address newContract)
{
Cookie c = new Cookie();
contracts.push(c);
return c;
}
}


contract Cookie {

// suppose the deployed contract has a purpose

function getFlavor()
public
constant
returns (string flavor)
{
return "mmm ... chocolate chip";
}
}


(referenced from https://ethereum.stackexchange.com/questions/13415/deploy-contract-from-contract-in-solidity)



This is a powerful feature in DAPP development, as it allows you to build an object oriented structure for your DAPP where requests can create new contracts. It is a well established design pattern, so what would the equivalent be in the Tezos ecosystem?










share|improve this question























  • It appears like CREATE_CONTRACT { storage 'g ; parameter 'p ; code ... } would work, but this will bloat the size of a contract a bit, and it feels like there should be a way to handle this gracefully like in Solidity's Java style class instantiation.

    – Rob
    Mar 11 at 23:54











  • If not, a clean example in Michelson would be nice.

    – Rob
    Mar 11 at 23:56













  • ok cool, probably a ways out then.

    – Rob
    Mar 12 at 0:24






  • 1





    I put a comment that I deleted to convert it into an answer. I missed your comment that was added afterwards. My apologies for this.

    – FFF
    Mar 12 at 0:34














4












4








4


1






Has there been any research into how a contract factory might be made in Michelson/Liquidity?



To elaborate, in Solidity a contract factory might look like:



pragma solidity ^0.4.8;

contract Bakery {

// index of created contracts

address public contracts;

// useful to know the row count in contracts index

function getContractCount()
public
constant
returns(uint contractCount)
{
return contracts.length;
}

// deploy a new contract

function newCookie()
public
returns(address newContract)
{
Cookie c = new Cookie();
contracts.push(c);
return c;
}
}


contract Cookie {

// suppose the deployed contract has a purpose

function getFlavor()
public
constant
returns (string flavor)
{
return "mmm ... chocolate chip";
}
}


(referenced from https://ethereum.stackexchange.com/questions/13415/deploy-contract-from-contract-in-solidity)



This is a powerful feature in DAPP development, as it allows you to build an object oriented structure for your DAPP where requests can create new contracts. It is a well established design pattern, so what would the equivalent be in the Tezos ecosystem?










share|improve this question














Has there been any research into how a contract factory might be made in Michelson/Liquidity?



To elaborate, in Solidity a contract factory might look like:



pragma solidity ^0.4.8;

contract Bakery {

// index of created contracts

address public contracts;

// useful to know the row count in contracts index

function getContractCount()
public
constant
returns(uint contractCount)
{
return contracts.length;
}

// deploy a new contract

function newCookie()
public
returns(address newContract)
{
Cookie c = new Cookie();
contracts.push(c);
return c;
}
}


contract Cookie {

// suppose the deployed contract has a purpose

function getFlavor()
public
constant
returns (string flavor)
{
return "mmm ... chocolate chip";
}
}


(referenced from https://ethereum.stackexchange.com/questions/13415/deploy-contract-from-contract-in-solidity)



This is a powerful feature in DAPP development, as it allows you to build an object oriented structure for your DAPP where requests can create new contracts. It is a well established design pattern, so what would the equivalent be in the Tezos ecosystem?







michelson






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Mar 11 at 23:42









RobRob

3607




3607













  • It appears like CREATE_CONTRACT { storage 'g ; parameter 'p ; code ... } would work, but this will bloat the size of a contract a bit, and it feels like there should be a way to handle this gracefully like in Solidity's Java style class instantiation.

    – Rob
    Mar 11 at 23:54











  • If not, a clean example in Michelson would be nice.

    – Rob
    Mar 11 at 23:56













  • ok cool, probably a ways out then.

    – Rob
    Mar 12 at 0:24






  • 1





    I put a comment that I deleted to convert it into an answer. I missed your comment that was added afterwards. My apologies for this.

    – FFF
    Mar 12 at 0:34



















  • It appears like CREATE_CONTRACT { storage 'g ; parameter 'p ; code ... } would work, but this will bloat the size of a contract a bit, and it feels like there should be a way to handle this gracefully like in Solidity's Java style class instantiation.

    – Rob
    Mar 11 at 23:54











  • If not, a clean example in Michelson would be nice.

    – Rob
    Mar 11 at 23:56













  • ok cool, probably a ways out then.

    – Rob
    Mar 12 at 0:24






  • 1





    I put a comment that I deleted to convert it into an answer. I missed your comment that was added afterwards. My apologies for this.

    – FFF
    Mar 12 at 0:34

















It appears like CREATE_CONTRACT { storage 'g ; parameter 'p ; code ... } would work, but this will bloat the size of a contract a bit, and it feels like there should be a way to handle this gracefully like in Solidity's Java style class instantiation.

– Rob
Mar 11 at 23:54





It appears like CREATE_CONTRACT { storage 'g ; parameter 'p ; code ... } would work, but this will bloat the size of a contract a bit, and it feels like there should be a way to handle this gracefully like in Solidity's Java style class instantiation.

– Rob
Mar 11 at 23:54













If not, a clean example in Michelson would be nice.

– Rob
Mar 11 at 23:56







If not, a clean example in Michelson would be nice.

– Rob
Mar 11 at 23:56















ok cool, probably a ways out then.

– Rob
Mar 12 at 0:24





ok cool, probably a ways out then.

– Rob
Mar 12 at 0:24




1




1





I put a comment that I deleted to convert it into an answer. I missed your comment that was added afterwards. My apologies for this.

– FFF
Mar 12 at 0:34





I put a comment that I deleted to convert it into an answer. I missed your comment that was added afterwards. My apologies for this.

– FFF
Mar 12 at 0:34










2 Answers
2






active

oldest

votes


















3














There is a very succinct discussion in the announcement for SmartPy https://medium.com/@SmartPy_io/introducing-smartpy-and-smartpy-io-d4013bee7d4e#15ee.



The idea is to have a contract that holds a big_map and each element of the big_map represents a contract.



This is absolutely not restricted to SmartPy and it is directly doable in Michelson, Liquidity or Fi.



This subject also appeared here:
What is the BigMap container and why does it matter?






share|improve this answer


























  • I appreciate your response and don't want this to come across negative, but I feel we need to come up with a more comprehensive solution to this problem in the near term to make DAPP development productive.

    – Rob
    Mar 12 at 7:35











  • I can easily agree that this is not the final and only solution.

    – FFF
    Mar 12 at 11:52











  • reference below to see an example of what I was thinking

    – Rob
    Mar 14 at 4:36



















2














Here's an example of a contract handling this in liquidity. There's the unique challenge of writing functions that can only utilize remote procedure calls at the end of their execution:



type plus_storage = {
count: nat,
plus_owner: address,
};

contract PlusOne = {
type storage = plus_storage;
let%init storage = (y: nat) => {
count: y,
plus_owner: Current.sender(),
};
let%entry main = (p: nat, storage) => {
if (Current.sender() != storage.plus_owner) {
failwith("invalid caller");
};
(, storage);
}
};

type storage = {
owner: key,
pl: address,
};

let%init storage = (contract_owner: key) => {
owner: contract_owner,
pl: KT1111111111111111111111111111111111,
}

let%entry other = (param: nat, storage) => {
let t: option(PlusOne.instance) = Contract.at(storage.pl);
let t = switch(t) {
| None => Current.failwith()
| Some(inst) => inst
};
let op = Contract.call(
~dest=t,
~amount=0tz,
~entry=main,
~parameter=param);
([op], storage);
};

let%entry main = ((), storage) => {
let manager = Crypto.hash_key(storage.owner);
let delegate = Some(manager);
let spendable = false;
let amount = Current.amount();
let init_value: nat = 0;

let (c_op, c_addr) =
Contract.create(
~manager,
~delegate,
~spendable,
~delegatable=false,
~amount,
~storage={count: init_value, plus_owner: Contract.address(Contract.self())},
(contract PlusOne),
);

let storage = storage.pl = c_addr;
([c_op], storage);
};


It makes me wonder if this will lead to endpoints that are like "order" and "pickup", ie a restaurant.






share|improve this answer
























    Your Answer








    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "698"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: false,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    noCode: true, onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftezos.stackexchange.com%2fquestions%2f745%2fcontract-factories%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    3














    There is a very succinct discussion in the announcement for SmartPy https://medium.com/@SmartPy_io/introducing-smartpy-and-smartpy-io-d4013bee7d4e#15ee.



    The idea is to have a contract that holds a big_map and each element of the big_map represents a contract.



    This is absolutely not restricted to SmartPy and it is directly doable in Michelson, Liquidity or Fi.



    This subject also appeared here:
    What is the BigMap container and why does it matter?






    share|improve this answer


























    • I appreciate your response and don't want this to come across negative, but I feel we need to come up with a more comprehensive solution to this problem in the near term to make DAPP development productive.

      – Rob
      Mar 12 at 7:35











    • I can easily agree that this is not the final and only solution.

      – FFF
      Mar 12 at 11:52











    • reference below to see an example of what I was thinking

      – Rob
      Mar 14 at 4:36
















    3














    There is a very succinct discussion in the announcement for SmartPy https://medium.com/@SmartPy_io/introducing-smartpy-and-smartpy-io-d4013bee7d4e#15ee.



    The idea is to have a contract that holds a big_map and each element of the big_map represents a contract.



    This is absolutely not restricted to SmartPy and it is directly doable in Michelson, Liquidity or Fi.



    This subject also appeared here:
    What is the BigMap container and why does it matter?






    share|improve this answer


























    • I appreciate your response and don't want this to come across negative, but I feel we need to come up with a more comprehensive solution to this problem in the near term to make DAPP development productive.

      – Rob
      Mar 12 at 7:35











    • I can easily agree that this is not the final and only solution.

      – FFF
      Mar 12 at 11:52











    • reference below to see an example of what I was thinking

      – Rob
      Mar 14 at 4:36














    3












    3








    3







    There is a very succinct discussion in the announcement for SmartPy https://medium.com/@SmartPy_io/introducing-smartpy-and-smartpy-io-d4013bee7d4e#15ee.



    The idea is to have a contract that holds a big_map and each element of the big_map represents a contract.



    This is absolutely not restricted to SmartPy and it is directly doable in Michelson, Liquidity or Fi.



    This subject also appeared here:
    What is the BigMap container and why does it matter?






    share|improve this answer















    There is a very succinct discussion in the announcement for SmartPy https://medium.com/@SmartPy_io/introducing-smartpy-and-smartpy-io-d4013bee7d4e#15ee.



    The idea is to have a contract that holds a big_map and each element of the big_map represents a contract.



    This is absolutely not restricted to SmartPy and it is directly doable in Michelson, Liquidity or Fi.



    This subject also appeared here:
    What is the BigMap container and why does it matter?







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Mar 12 at 0:35

























    answered Mar 12 at 0:26









    FFFFFF

    723312




    723312













    • I appreciate your response and don't want this to come across negative, but I feel we need to come up with a more comprehensive solution to this problem in the near term to make DAPP development productive.

      – Rob
      Mar 12 at 7:35











    • I can easily agree that this is not the final and only solution.

      – FFF
      Mar 12 at 11:52











    • reference below to see an example of what I was thinking

      – Rob
      Mar 14 at 4:36



















    • I appreciate your response and don't want this to come across negative, but I feel we need to come up with a more comprehensive solution to this problem in the near term to make DAPP development productive.

      – Rob
      Mar 12 at 7:35











    • I can easily agree that this is not the final and only solution.

      – FFF
      Mar 12 at 11:52











    • reference below to see an example of what I was thinking

      – Rob
      Mar 14 at 4:36

















    I appreciate your response and don't want this to come across negative, but I feel we need to come up with a more comprehensive solution to this problem in the near term to make DAPP development productive.

    – Rob
    Mar 12 at 7:35





    I appreciate your response and don't want this to come across negative, but I feel we need to come up with a more comprehensive solution to this problem in the near term to make DAPP development productive.

    – Rob
    Mar 12 at 7:35













    I can easily agree that this is not the final and only solution.

    – FFF
    Mar 12 at 11:52





    I can easily agree that this is not the final and only solution.

    – FFF
    Mar 12 at 11:52













    reference below to see an example of what I was thinking

    – Rob
    Mar 14 at 4:36





    reference below to see an example of what I was thinking

    – Rob
    Mar 14 at 4:36











    2














    Here's an example of a contract handling this in liquidity. There's the unique challenge of writing functions that can only utilize remote procedure calls at the end of their execution:



    type plus_storage = {
    count: nat,
    plus_owner: address,
    };

    contract PlusOne = {
    type storage = plus_storage;
    let%init storage = (y: nat) => {
    count: y,
    plus_owner: Current.sender(),
    };
    let%entry main = (p: nat, storage) => {
    if (Current.sender() != storage.plus_owner) {
    failwith("invalid caller");
    };
    (, storage);
    }
    };

    type storage = {
    owner: key,
    pl: address,
    };

    let%init storage = (contract_owner: key) => {
    owner: contract_owner,
    pl: KT1111111111111111111111111111111111,
    }

    let%entry other = (param: nat, storage) => {
    let t: option(PlusOne.instance) = Contract.at(storage.pl);
    let t = switch(t) {
    | None => Current.failwith()
    | Some(inst) => inst
    };
    let op = Contract.call(
    ~dest=t,
    ~amount=0tz,
    ~entry=main,
    ~parameter=param);
    ([op], storage);
    };

    let%entry main = ((), storage) => {
    let manager = Crypto.hash_key(storage.owner);
    let delegate = Some(manager);
    let spendable = false;
    let amount = Current.amount();
    let init_value: nat = 0;

    let (c_op, c_addr) =
    Contract.create(
    ~manager,
    ~delegate,
    ~spendable,
    ~delegatable=false,
    ~amount,
    ~storage={count: init_value, plus_owner: Contract.address(Contract.self())},
    (contract PlusOne),
    );

    let storage = storage.pl = c_addr;
    ([c_op], storage);
    };


    It makes me wonder if this will lead to endpoints that are like "order" and "pickup", ie a restaurant.






    share|improve this answer




























      2














      Here's an example of a contract handling this in liquidity. There's the unique challenge of writing functions that can only utilize remote procedure calls at the end of their execution:



      type plus_storage = {
      count: nat,
      plus_owner: address,
      };

      contract PlusOne = {
      type storage = plus_storage;
      let%init storage = (y: nat) => {
      count: y,
      plus_owner: Current.sender(),
      };
      let%entry main = (p: nat, storage) => {
      if (Current.sender() != storage.plus_owner) {
      failwith("invalid caller");
      };
      (, storage);
      }
      };

      type storage = {
      owner: key,
      pl: address,
      };

      let%init storage = (contract_owner: key) => {
      owner: contract_owner,
      pl: KT1111111111111111111111111111111111,
      }

      let%entry other = (param: nat, storage) => {
      let t: option(PlusOne.instance) = Contract.at(storage.pl);
      let t = switch(t) {
      | None => Current.failwith()
      | Some(inst) => inst
      };
      let op = Contract.call(
      ~dest=t,
      ~amount=0tz,
      ~entry=main,
      ~parameter=param);
      ([op], storage);
      };

      let%entry main = ((), storage) => {
      let manager = Crypto.hash_key(storage.owner);
      let delegate = Some(manager);
      let spendable = false;
      let amount = Current.amount();
      let init_value: nat = 0;

      let (c_op, c_addr) =
      Contract.create(
      ~manager,
      ~delegate,
      ~spendable,
      ~delegatable=false,
      ~amount,
      ~storage={count: init_value, plus_owner: Contract.address(Contract.self())},
      (contract PlusOne),
      );

      let storage = storage.pl = c_addr;
      ([c_op], storage);
      };


      It makes me wonder if this will lead to endpoints that are like "order" and "pickup", ie a restaurant.






      share|improve this answer


























        2












        2








        2







        Here's an example of a contract handling this in liquidity. There's the unique challenge of writing functions that can only utilize remote procedure calls at the end of their execution:



        type plus_storage = {
        count: nat,
        plus_owner: address,
        };

        contract PlusOne = {
        type storage = plus_storage;
        let%init storage = (y: nat) => {
        count: y,
        plus_owner: Current.sender(),
        };
        let%entry main = (p: nat, storage) => {
        if (Current.sender() != storage.plus_owner) {
        failwith("invalid caller");
        };
        (, storage);
        }
        };

        type storage = {
        owner: key,
        pl: address,
        };

        let%init storage = (contract_owner: key) => {
        owner: contract_owner,
        pl: KT1111111111111111111111111111111111,
        }

        let%entry other = (param: nat, storage) => {
        let t: option(PlusOne.instance) = Contract.at(storage.pl);
        let t = switch(t) {
        | None => Current.failwith()
        | Some(inst) => inst
        };
        let op = Contract.call(
        ~dest=t,
        ~amount=0tz,
        ~entry=main,
        ~parameter=param);
        ([op], storage);
        };

        let%entry main = ((), storage) => {
        let manager = Crypto.hash_key(storage.owner);
        let delegate = Some(manager);
        let spendable = false;
        let amount = Current.amount();
        let init_value: nat = 0;

        let (c_op, c_addr) =
        Contract.create(
        ~manager,
        ~delegate,
        ~spendable,
        ~delegatable=false,
        ~amount,
        ~storage={count: init_value, plus_owner: Contract.address(Contract.self())},
        (contract PlusOne),
        );

        let storage = storage.pl = c_addr;
        ([c_op], storage);
        };


        It makes me wonder if this will lead to endpoints that are like "order" and "pickup", ie a restaurant.






        share|improve this answer













        Here's an example of a contract handling this in liquidity. There's the unique challenge of writing functions that can only utilize remote procedure calls at the end of their execution:



        type plus_storage = {
        count: nat,
        plus_owner: address,
        };

        contract PlusOne = {
        type storage = plus_storage;
        let%init storage = (y: nat) => {
        count: y,
        plus_owner: Current.sender(),
        };
        let%entry main = (p: nat, storage) => {
        if (Current.sender() != storage.plus_owner) {
        failwith("invalid caller");
        };
        (, storage);
        }
        };

        type storage = {
        owner: key,
        pl: address,
        };

        let%init storage = (contract_owner: key) => {
        owner: contract_owner,
        pl: KT1111111111111111111111111111111111,
        }

        let%entry other = (param: nat, storage) => {
        let t: option(PlusOne.instance) = Contract.at(storage.pl);
        let t = switch(t) {
        | None => Current.failwith()
        | Some(inst) => inst
        };
        let op = Contract.call(
        ~dest=t,
        ~amount=0tz,
        ~entry=main,
        ~parameter=param);
        ([op], storage);
        };

        let%entry main = ((), storage) => {
        let manager = Crypto.hash_key(storage.owner);
        let delegate = Some(manager);
        let spendable = false;
        let amount = Current.amount();
        let init_value: nat = 0;

        let (c_op, c_addr) =
        Contract.create(
        ~manager,
        ~delegate,
        ~spendable,
        ~delegatable=false,
        ~amount,
        ~storage={count: init_value, plus_owner: Contract.address(Contract.self())},
        (contract PlusOne),
        );

        let storage = storage.pl = c_addr;
        ([c_op], storage);
        };


        It makes me wonder if this will lead to endpoints that are like "order" and "pickup", ie a restaurant.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Mar 14 at 4:36









        RobRob

        3607




        3607






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Tezos Stack Exchange!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftezos.stackexchange.com%2fquestions%2f745%2fcontract-factories%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            How do I know what Microsoft account the skydrive app is syncing to?

            When does type information flow backwards in C++?

            Grease: Live!