Hello everyone, here is a proposal to add a new system call in the core of koinos blockchain called get_contract_metadata. This system call is needed to improve the security of the tokens and NFTs.
<p dir="auto">Before digging into the details, let's take a look to Ethereum, how they handle the authorizations, and then let's come back to koinos and see the differences. <h3>Ethereum <p dir="auto">Let's say you call the contrat A. This contract calls the contract B. This one the contract C. And this final contract tries to make a transfer of tokens from your account to another address. In summary is A -> B -> C -> transfer wEth. What is the process to authorize this transaction? In ethereum there are 2 addresses: <ul> <li><code>tx.origin: This is the external owned account (EOA), that is, the user that signs the transaction. <li><code>msg.sender: This is the address that triggers the transfer. It could be a contract account or again the tx.origin. In our example it is the Contract C, the address that triggered the transfer. <p dir="auto">The ERC20 token contract only allows to move tokens from the <code>msg.sender account when using the <code>transfer function. That is, the transfer is done only if you make the transfer directly. But if you are <code>tx.origin and the contract in the middle is <code>msg.sender then your funds are safe because <code>tx.origin is not involved in this process. <p dir="auto">But then, how the contract C can actually move the tokens from the user? the answer is the <code>transferFrom function. In order to add more options to make transfers in ethereum, they introduced "allowances". So first, you have to allow to a specific contract to spend your tokens. Then this contract can call the <code>transferFrom function to actually move the tokens. <p dir="auto">This allowance has to be set in a previous transaction. <h3>Koinos <p dir="auto">Koinos introduced a new model for authorisations. When a transfer of koin is called, the contract does the following process: <p dir="auto">If the <code>caller of the koin contract is the owner of the tokens then the transaction is accepted. This is more or less similar to the <code>msg.sender of ethereum, but there is a difference: The <code>caller of koinos is just for contracts, not external accounts. This means that if the user signs a transaction to call the koin contract directly, he is not considered as <code>caller. The caller is empty in this case. <p dir="auto">But then how it works? When the caller is not authorized, the koin contract calls the <code>checkAuthority(from) system call, where <code>from is the account that owns the tokens. <p dir="auto">This system call works in this way: <ul> <li>If <code>from is a smart contract, then the chain will call it to ask if it authorizes the transfer. Then the transfer is accepted only if this contract replies YES. The advantage is that this contract could contain any logic to determine if the transaction is accepted or not. <li>If <code>from is not a smart contract, then the chain will check if the transaction was signed by <code>from. So, this is like the equivalent of <code>tx.origin in ethereum. <p dir="auto">This last point has a risk, because this means that a contract in the middle can request to make a transfer and it will be accepted because the user signed the transaction in the first place. <p dir="auto">Please note that in ethereum, the <code>tx.origin is not involved in the transaction to not affect his assets. However, in koinos it is taken into account and this can put in risk the assets of the user. Here is a summary of the different scenarios: <div class="table-responsive"><table> <thead> <tr><th>Action<th>Ethereum<th>Koinos <tbody> <tr><td>User calls the token contract directly<td>User is <code>msg.sender. Transfer accepted<td>User is not <code>caller. User signed the transaction. Transfer accepted <tr><td>User has a contract and this one calls the token contract<td>User is <code>msg.sender. Transfer accepted<td>User is <code>caller. Transfer accepted <tr><td>User calls contract C and this one calls the token contract<td>User is not <code>msg.sender. Transfer accepted only if the user defined an allowance for C in a previous tx<td>User is not <code>caller. User signed transaction. Transfer accepted ⚠️ <tr><td>User has a contract, calls contract C and this one calls the token contract<td>User is not <code>msg.sender. Transfer accepted only if the user defined an allowance for C in a previous tx<td>User is not <code>caller. Transfer accepted only if the contract of the user allows the operation. <h3>How to improve the security in koinos? <p dir="auto">The principal problem is the involvement of the <code>tx.origin in the authorization. In other words, the problem is that the signature of the user is accepted without taking into account who is the <code>caller.<br /> The solution is to do something similar to Ethereum (defining allowances), and at the same time trying to keep the good parts of the authorization model of koinos. So the proposal for the token contracts is this one: <pre><code>// transfer from A to B if (caller == A) { // equivalent of msg.sender isAuthorized = true; } else if (caller has allowance) { // equivalent of transferFrom isAuthorized = true; } else if (A has a contract) { // novel authority function of koinos. // no equivalent in ethereum isAuthorized = ask_contract_A(); } else if (no caller && tx signer == A) { // equivalent of msg.sender isAuthorized = true; } else { isAuthorized = false; } <p dir="auto">This logic can not be implemented with the current tools in koinos because the <code>checkAuthority function is the unique one that can check if the user has a contract, but its problem is that it doesn't take into account the caller when checking the signature. <h3>Koinos proposal - Part 1 - get_contract_metadata <p dir="auto">Create a new system call to get the contract metadata of a specific address. Then it can be used to know if an account has a smart contract and or not. <p dir="auto"><span>Roamin already created the code for this change. You can check it in this pull request: <a href="https://github.com/koinos/koinos-contracts-as/pull/100" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">https://github.com/koinos/koinos-contracts-as/pull/100 <h3>Koinos proposal - Part 2 - update token contracts <p dir="auto">Once the first part is done, then we can rewrite the token contracts in order to introduce the new authorization logic described above. <p dir="auto">As you can notice, the <code>checkAuthority system call is not used anymore. Instead of that, we define an internal function in the contract to handle this authorization, and it calls the new <code>get_contract_metadata system call to know if the user has a contract. <p dir="auto"><span>I already created a token contract for this change. You can check the implementation here <a href="https://github.com/joticajulian/koinos-contracts-as/blob/main/contracts/token/assembly/Token.ts" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">https://github.com/joticajulian/koinos-contracts-as/blob/main/contracts/token/assembly/Token.ts <p dir="auto">It still needs the adaptation of the new system call, but it already has the allowances. Koin DX is already using this token contract as reference. <p dir="auto">The idea is to use it as standard, and update the KOIN and VHP contracts using this logic. <h1>Polls to vote <p dir="auto">These proposals can be voted here: <ul> <li><span>New system call to get contract metadata: <a href="https://koinosbox.com/polls/1" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">https://koinosbox.com/polls/1 <li><span>Update KOIN and VHP contracts: <a href="https://koinosbox.com/polls/2" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">https://koinosbox.com/polls/2 <p dir="auto"><strong><em>Edit: <em>I forgot that the authorize function can only be called in kernel mode, and not by normal contracts. This means that the part where the token contract calls the authorize function of the user is not applicable. Then it is better to update the check authority system call and use it in the token contracts. The update consist in protect the user by allowing the signature ONLY if the caller is empty. <p dir="auto"><em>With regarding to the get contract metadata system call it is not useful anymore for the token contracts. However, it can be useful for other use cases.last year in #koinos by jga (68)
$26.07
- Past Payouts $26.07
- - Author $13.04
- - Curators $13.03
51 votes
- trafalgar: $20.23
- traf: $1.70
- fredrikaa: $1.01
- lordbutterfly: $0.91
- eturnerx: $0.44
- raindrop: $0.31
- themonetaryfew: $0.27
- sorin.cristescu: $0.25
- bluerobo: $0.16
- kevinwong: $0.12
- fw206: $0.10
- penguinpablo: $0.09
- cwow1: $0.09
- olebulls: $0.07
- cervisia: $0.05
- nenio: $0.03
- kattycrochet: $0.03
- smartvote: $0.02
- omegaraptor: $0.02
- photographercr: $0.02
- and 31 more