Skip to content
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

[feature] Charity address generator #53

Closed
vncoelho opened this issue Jun 19, 2018 · 16 comments
Closed

[feature] Charity address generator #53

vncoelho opened this issue Jun 19, 2018 · 16 comments

Comments

@vncoelho
Copy link
Member

vncoelho commented Jun 19, 2018

Hi, everyone.

@lerider commented about his idea to design a donation address, which would be able to send GAS but do not send Neo assets (claim would be a source of tokens for the charity and is, consequently, needed. Thus, send NEO to itself should be allowed).

The first idea (@igormcoelho) was to design something like this:

// NEP Charity Donations - Remote GAS Claim
using Neo.SmartContract.Framework;
using Neo.SmartContract.Framework.Services.Neo;
using Neo.SmartContract.Framework.Services.System;
using System;

namespace Neo.SmartContract
{
    public class NepCharityDonation : Framework.SmartContract
    {
        private static readonly byte[] Owner = "AK2nJJpJr6o664CWJKi1QRXjqeic2zRp8y".ToScriptHash();
        private static readonly byte[] Charity = "APLJBPhtRg2XLhtpxEHd6aRNL7YSLGH2ZL".ToScriptHash();
        private static readonly byte[] NeoAssetId = { 155, 124, 255, 218, 166, 116, 190, 174, 15, 147, 14, 190, 96, 133, 175, 144, 147, 229, 254, 86, 179, 74, 92, 34, 12, 205, 207, 110, 252, 51, 111, 197 };
        private static readonly byte[] GasAssetId = { 231, 45, 40, 105, 121, 238, 108, 177, 183, 230, 93, 253, 223, 178, 227, 132, 16, 11, 141, 20, 142, 119, 88, 222, 66, 228, 22, 139, 113, 121, 44, 96 };

        // Verification Contract (no need for deploy)
        public static bool Main()
        {
            // Owner can manage all funds
            if(Runtime.CheckWitness(Owner))
               return true;
            // Verify if it's the Charity address   
            if(Runtime.CheckWitness(Charity))
            {
                // Get outputs
                Transaction tx = (Transaction)ExecutionEngine.ScriptContainer;
                TransactionOutput[] outputs = tx.GetOutputs();
                // Verify if this is a self transfer of NEO
                if((outputs.Length == 1) && (outputs[0].AssetId == NeoAssetId) && (outputs[0].ScriptHash == ExecutionEngine.ExecutingScriptHash))
                    return true;
                // Verifing if all outputs are GAS type
                foreach (TransactionOutput output in outputs)
                    if (output.AssetId != GasAssetId)
                        return false;
                return true;
            }
            
            return false;
        }
    }
}

However, we realized that we should use VerifySignature instead of Runtime.CheckWitness, which requires us to send signature as a parameter, right?

What do you recommend, @erikzhang ?

A1) VerifySignature would imply in an adjustment on the wallet for sending from this type of address.
A2) We could design other type of contract that blocks sending to other addresses.
But, perhaps, a password should be used for avoiding malicious transfer back to the OWNER (which would bother the charity address).

using Neo.SmartContract.Framework;
using Neo.SmartContract.Framework.Services.Neo;
using Neo.SmartContract.Framework.Services.System;
using System;
using System.ComponentModel;
using System.Numerics;

namespace NeoContract1
{
    public class CharitySimpleExample : SmartContract
    {

        private static readonly byte[] neo_asset_id = { 155, 124, 255, 218, 166, 116, 190, 174, 15, 147, 14, 190, 96, 133, 175, 144, 147, 229, 254, 86, 179, 74, 92, 34, 12, 205, 207, 110, 252, 51, 111, 197 };
	private static readonly byte[] gas_asset_id = { 231, 45, 40, 105, 121, 238, 108, 177, 183, 230, 93, 253, 223, 178, 227, 132, 16, 11, 141, 20, 142, 119, 88, 222, 66, 228, 22, 139, 113, 121, 44, 96 };

	//The guy who donate the NEO for charity and can without anytime
	public static readonly byte[] Owner = "ATrzHaicmhRj15C3Vv6e6gLfLqhSD2PtTr".ToScriptHash();

      
	//This is the unic addres able to transfer the GAS
	public static readonly byte[] RegisteredClaimAddres = "ATrzHaicmhRj15C3Vv6e6gLfLqhSD2PtTr".ToScriptHash();

        public static object Main(string operation, params object[] args)
        {
            if (Runtime.Trigger == TriggerType.Verification)
            {

                if (operation == "ownerWithdrawn")
                {
                    // if param Owner is script hash
                    return Runtime.CheckWitness(Owner);
                }

               
               Transaction tx = (Transaction)ExecutionEngine.ScriptContainer;
               TransactionOutput[] outputs = tx.GetOutputs();
               TransactionInput[] inputs = tx.GetInputs();
               
               bool canWithdraw = true;
               foreach (TransactionOutput output in outputs)
               {
                	if (output.AssetId == gas_asset_id && output.ScriptHash != RegisteredClaimAddres)
                	{
			    canWithdraw = false;
			}

                	if (output.AssetId == neo_asset_id && output.ScriptHash != Owner)
                	{
			    canWithdraw = false;
			}
               } 
               
               return canWithdraw;
            }//finish trigger verification, the only one able to withdraw

	        return false;         
        }

    }
}
@vncoelho vncoelho changed the title [feature] Charity addresses generator [feature] Charity address generator Jun 19, 2018
@erikzhang
Copy link
Member

Is this a proposal? It's not a dapp?

@vncoelho
Copy link
Member Author

vncoelho commented Jun 25, 2018

Hi, Erik.
In fact, maybe it should be a standard. We would use this "dapp" for generating addresses, which, if used, should interact with light wallets.
In this verification only dapp:

  • only a registered address would receive the generated GAS (the SC would only be able to send GAS assets to this address);

  • The "donated" Neo could only return to the Owner (which donated it). Perhaps, we could insert a password as parameter, for avoiding an attack of returning the Neo to the original Owner.

    I think that is it just a Verification Smart Contract, not an application itself (which could be used as an address generator).
    This was an idea that @lerider wants to realize, for donation purpose.

    Do you think is it possible, safe or useful to create such kind of address generator?
    If not, talk with Lerider....eahueahueaheua 💃

@erikzhang
Copy link
Member

I think this could be a template, not a standard.

@vncoelho
Copy link
Member Author

Yes, a template. You are right.

We just worry, a little bit, if the Wallet Clients would know how to handle such contracts.
For a better user experience, if it is a kind of standard, the invocation could be a "native" call of from wallets.

@erikzhang
Copy link
Member

Wallets can handle it with its ABI. See https://github.com/neo-project/proposals/blob/master/nep-3.mediawiki

@vncoelho
Copy link
Member Author

vncoelho commented Jun 25, 2018

Precise as a 🗡️

The ABI template is useful and well-described, the C# ABI info is used at https://neocompiler.io/#/ecolab
Unfortunately, perhaps, the only language that supports it.
We already tried to motivate other developers to include it in their projects.
But now we will keep recommending them to follow NEP-3.

A template + its standard generated ABI should be enough.
For this contract, it would be kind of empty (also because it is very simple template):

ScriptHash (reversed): 0x6498ad39351b4363bf3f8c22def9f338462200bd
Entry Point:Main
Functions:
	Any Main(String passwordForClaimingAllNeoBackToOwner_OneTimeCall_Then_Discarded);
Events:

It needs to be split in some additional functions, which would help comprehension.

@igormcoelho
Copy link

igormcoelho commented Jun 30, 2018

@vncoelho I think we can do that as a regular wallet as @erikzhang mentioned (using some OpCode magic tricks):

// NEP Charity Donations - Remote GAS Claim
using Neo.SmartContract.Framework;
using Neo.SmartContract.Framework.Services.Neo;
using Neo.SmartContract.Framework.Services.System;
using System;
using Neo.VM;

namespace Neo.SmartContract
{
    public class NepCharityDonation : Framework.SmartContract
    {
        [OpCode(OpCode.CHECKSIG)]
        protected extern static bool VerifySignature2(byte[] pubkey);
        
        [OpCode(OpCode.DUP)]
        protected extern static void Duplicate();

        [OpCode(OpCode.DROP)]
        protected extern static void Drop();

        //private static readonly byte[] OwnerSH = "AK2nJJpJr6o664CWJKi1QRXjqeic2zRp8y".ToScriptHash();
        //private static readonly byte[] CharitySH = "APLJBPhtRg2XLhtpxEHd6aRNL7YSLGH2ZL".ToScriptHash();
        public static readonly byte[] Owner = "031a6c6fbbdf02ca351745fa86b9ba5a9452d785ac4f7fc2b7548ca2a46c4fcf4a".HexToBytes();
        public static readonly byte[] Charity = "036245f426b4522e8a2901be6ccc1f71e37dc376726cc6665d80c5997e240568fb".HexToBytes();
        
        private static readonly byte[] NeoAssetId = { 155, 124, 255, 218, 166, 116, 190, 174, 15, 147, 14, 190, 96, 133, 175, 144, 147, 229, 254, 86, 179, 74, 92, 34, 12, 205, 207, 110, 252, 51, 111, 197 };
        private static readonly byte[] GasAssetId = { 231, 45, 40, 105, 121, 238, 108, 177, 183, 230, 93, 253, 223, 178, 227, 132, 16, 11, 141, 20, 142, 119, 88, 222, 66, 228, 22, 139, 113, 121, 44, 96 };

        // Verification Contract (no need for deploy)
        public static bool Main()
        {
            if (Runtime.Trigger != TriggerType.Verification) // see NEP-7 final situation
		        throw new Exception();
		        
            Duplicate(); // duplicate signature on main stack
            
            // Owner can manage all funds
            //if(Runtime.CheckWitness(Owner))
            if(VerifySignature2(Owner)) {
                Drop(); // eliminate second signature from main stack
                return true;
            }
            
            // Verify if it's the Charity address   
            //if(Runtime.CheckWitness(Charity))
            if(VerifySignature2(Charity)) {
                // Get outputs
                Transaction tx = (Transaction)ExecutionEngine.ScriptContainer;
                TransactionOutput[] outputs = tx.GetOutputs();
                // Verify if this is a self transfer of NEO
                if((outputs.Length == 1) && (outputs[0].AssetId == NeoAssetId) && (outputs[0].ScriptHash == ExecutionEngine.ExecutingScriptHash))
                    return true;
                // Verifing if all outputs are GAS type
                foreach (TransactionOutput output in outputs)
                    if (output.AssetId != GasAssetId)
                        return false;
                return true;
            }
            
            return false;
        }
    }
}

@igormcoelho
Copy link

igormcoelho commented Sep 26, 2018

@vncoelho @lerider Finally, this example is working under SMACCO logic: https://github.com/neoresearch/smacco (https://neoresearch.io/smacco-demo)

{
  "standard": "smacco-1.0",
  "input_type" : "single",
  "pubkey_list" : ["031a6c6fbbdf02ca351745fa86b9ba5a9452d785ac4f7fc2b7548ca2a46c4fcf4a", "036245f426b4522e8a2901be6ccc1f71e37dc376726cc6665d80c5997e240568fb"],
  "rules" : [
    {
      "rule_type": "ALLOW_IF",
      "condition" : {
        "condition_type" : "CHECKSIG",
        "pubkey" : "0"
      },
    },
    {
      "rule_type": "ALLOW_IF",
      "condition" : {
        "condition_type" : "AND",
        "conditions" : [
          {
            "condition_type" : "CHECKSIG",
            "pubkey" : "1"
          },
          {
            "condition_type" : "OR",
            "conditions" : [
              {
                "condition_type" : "AND",
                "conditions" : [
                  {
                    "condition_type" : "SELF_TRANSFER"
                  },
                  {
                    "condition_type" : "ONLY_NEO"
                  }
                ]
              },
              {
                "condition_type" : "ONLY_GAS"
              }
            ]
          },
        ]
      },
    },
  ],
  "default_rule" : "DENY_ALL"
}

It can also be compiled and generate Address online at: https://neoresearch.io/smacco-demo

@vncoelho
Copy link
Member Author

vncoelho commented Sep 27, 2018

Incredible, brother. You did this like a Leopard. Impressive.
This deserve a nice tutorial.

Lets include this in our course for the 4th quarter of 2018

@igormcoelho
Copy link

igormcoelho commented Sep 28, 2018

It generates C# and flowchart automatically now ;) Classic timelock (https://neoresearch.io/smacco):

image

@vncoelho vncoelho reopened this Sep 28, 2018
@vncoelho
Copy link
Member Author

This issue was reopened due to the great effort and work done for reaching this impressive Smart Account Composer.
As soon as we finish the report we can close it again 🗡️
Thanks for this great insight, as well as the fast and precise work, Aiiigor.

@igormcoelho
Copy link

igormcoelho commented Sep 28, 2018

neo-smacco project is freely available at: https://neoresearch.io/smacco

Perhaps we can propose a NEP to replace smacco specification Vitor... then community may contribute with features that could be useful on most smart accounts. We already have timelock, multisig, asset limits, but we can think of many more. It would be nice to replace "standard": "smacco-1.0", with something more meaninful to the community, such as "standard": "NEP-1X", (perhaps together with Smart Transactions proposal? #67)

@vncoelho
Copy link
Member Author

Perfect, Igor.
Coming back to Brazil tomorrow, let's work on it!
I do not like to use "very", but, It is surely a very very important feature for putting Neo competitive with other Blockchains.

@vncoelho
Copy link
Member Author

Time to close this...aheuiaheuaea
SMACCO was a great tool and idea,@igormcoelho.

I still believe we should evolve the language and the tool further in a near future.

@shargon
Copy link
Member

shargon commented Jul 31, 2019

If we make verification turing incomplete, this never could be done

@vncoelho
Copy link
Member Author

No @shargon, it can be done, this was a template for UTXOs complex operation.
Now with native NEO and GAS it will be even easier.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants