In a previous post, I described the check_authority2
system call that was live on testnet. In that post I mentioned this point with regarding the arguments of the function:
This means that the
contract_id
is a trusted argument and the other ones could be faked by the assets contract. However, it's in the best interest of the assets contract to provide the correct information in these values to be able to operate its assets. Then the authorize function can trust in these values as well.
I discussed this with @vandeberg and @gerbino, and they considered that the other arguments should be trusted values as well to avoid side effects in the authorize function. And they proposed a different approach.
Recap of the problem
First, let's recap the problem of the current check authority function. In summary it works in this way:
_ | Caller | No caller |
---|---|---|
Smart wallet | call smart wallet | call smart wallet |
No smart wallet | check signatures⚠️ | check signatures |
If the account has a smart wallet, the wallet contract is called. If not, then the system checks if the account has signed the transaction. The point that we want to avoid here is the one with a warning mark in the table: When the transaction has a caller (contract calling a contract) it should not check the signatures. Please read this post for a more complete explanation.
Proposed solution
The proposed solution consists in the introduction of the get_contract_metadata
system call (with the ID 112), and use it to validate the conflicting point described above. If that point is ok then call the original check authority function. All of this process is wrapped in the System.checkAuthority
function of the SDK.
_ | Caller | No caller |
---|---|---|
Smart wallet | call smart wallet | call smart wallet |
No smart wallet | reject transaction | check signatures |
This approach consumes a little more resources with respect to the previous proposal check_authority2
because in certain conditions the system will read the contract metadata twice. But the advantage is that the arguments passed to the authorize function are trusted values because we continue using the native check authority function.
The code of the get_contract_metadata
function was created by Roamin. It can be found here.
I updated and released an alpha version for the new SDK. Check the code here.
How to test it
I deployed 3 simple contracts to make different tests:
- Assets Contract 1NCAnSYUKyvz2fUU6mWu9KWBQN4e2L4NPG: This is a contract that has assets from the users and uses check_authority function to verify the user. See the source code here.
- Third Party Contract 1Be4HHaVddFERRxWJHay69hDsJUA7zMzMG: This is a contract that calls the Assets Contract to operate with the assets of the user. See the source code here.
- Wallet Contract 1Hx33Z8eQFKBkDJ5WFcjJDGzXFJn5dnJMp: This is a smart contract wallet. It has the authority function overridden. See the source code here.
To test these 3 contracts you need Kondor installed in your browser. We will perform all the tests in https://harbinger.koinosblocks.com/, please go there and connect your wallet. Use your wallet to sign all transactions.
It's preferable to have tKoins in your account. If not you can use the "free mana" option available in kondor (each time you see the popup to send a transaction click advanced and select free mana).
Test #1: Interact with the Assets Contract
- Open the Assets Contract.
- Click operate assets and insert your account.
- Sign and send.
You called the assets contract directly, then it should work. Now click in "show transaction receipt". You should see this phrase in the logs "authorized to operate with the assets".
Test #2: Interact with the Third Party Contract
- Open the Third Party Contract.
- Click operate external assets and insert your account.
- Sign and send.
You called the third party contract and this contract called the assets contract. It should fail because the check_authority function does not accept a caller other than the user itself. And by the way, this is the most important behaviour we want to introduce with this new system call in order to protect the assets of the user.
If the use case requires this type of third party access for normal accounts the Assets Contract needs to implement allowances (this part will not be tested here since it's out of scope of the current system call).
Test #3: Smart wallet calling the Assets Contract
- Open the Wallet Contract.
- Click set allowance and put true.
- Sign and send (it doesn't matter if you are not the owner of this smart wallet. The set allowance function can be called by anyone just for testing purposes).
- Open the Assets Contract.
- Click operate assets and insert the account of the smart wallet (1Hx33Z8eQFKBkDJ5WFcjJDGzXFJn5dnJMp).
- Sign and send.
The Assets contract called the check_authority function, and this function called the authorize function of the smart wallet to approve the transaction. Since it was configured to accept it then it should work.
Click in "show transaction receipt". You should see several logs. In particular: "authorize called" and "authorized to operate with the assets".
Now repeat the whole test again but this time leave the field empty in allowance, which is the same as setting it to false. In this case it should fail.
Test #4: Third party calling the Assets Contract in name of the Smart wallet
- Open the Wallet Contract.
- Click set allowance and put true.
- Sign and send.
- Open the Third Party Contract.
- Click operate external assets and insert the account of the smart wallet (1Hx33Z8eQFKBkDJ5WFcjJDGzXFJn5dnJMp).
- Sign and send.
This test is very similar to the previous one. The third party calls the Assets contract and this one triggers the authorize function which returns true. Then the third party is authorized to access the assets.
Please note that here the check_authority function returns true despite of the fact that the third party is a contract calling another contract. This is because the rule of "rejecting a contract calling a contract" is only applicable when the account doesn't have smart wallets (see the table presented at the top).
Now click in "show transaction receipt". You should see similar logs as the previous test with the difference that now it says "caller: 1Be4HHaVddFERRxWJHay69hDsJUA7zMzMG", because it was triggered by a third party.
Repeat the whole test but set the allowance to false (remember that you have to leave the field empty). It should fail.
When mainnet?
We are close to launch this proposal in the mainnet. First, I'm going to let some time pass so that recognized members of the community and developers have time to test this new system call in the testnet. I will be answering questions and giving support if needed. After that, if everything continues well then I will submit the proposal in the mainnet 🚀
Thanks for sharing these content
Congratulations @jga! You have completed the following achievement on the Hive blockchain And have been rewarded with New badge(s)
Your next target is to reach 49000 upvotes.
You can view your badges on your board and compare yourself to others in the Ranking
If you no longer want to receive notifications, reply to this comment with the word
STOP