Skip to content

Commit

Permalink
Merge pull request #9 from demox-labs/master
Browse files Browse the repository at this point in the history
Add ARC-30: adding self.parent opcode
  • Loading branch information
howardwu authored Sep 20, 2022
2 parents 4cf51d6 + e0e6404 commit da3e3c6
Showing 1 changed file with 192 additions and 0 deletions.
192 changes: 192 additions & 0 deletions arc-0030/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
---
arc: 0030 # Add the next sequence number
title: Adding self.parent opcode # Title
authors: [email protected] [email protected] # Add all Github usernames, emails, and/or full names
discussion: ARC-0030: Adding self.parent opcode # Create a 'Github Discussion' titled 'ARC-XXXX: {TITLE}`
topic: Application # Choose: Protocol, Network, or Application
status: Draft
created: 9/2/2022 # Date
---

## Abstract

Let's get NFTs & Tokens/DeFI working on Aleo. Currently, you can create an ERC-20/ERC-721-like program on Aleo but it is severly limited.
The biggest limitation is that a program cannot own an NFT. This prevents these Aleo tokens from being used in: escrow, auctions, pools, etc.

In order to enable this functionality, we need an opcode in the Aleo instruction set like: `self.parent`. This opcode would be similar to `self.caller` except it would result in the address of the program who called another program.

By creating this opcode, we could design token/nft programs to enable ownership through a public mapping, enabling Aleo users to transfer assets to a program. A program could then hold them in escrow and only release them as dictated through the smart contract.

In ethereum, there's a concept of `tx.origin` -> `self.caller` and `msg.sender`. Currently, there's no `msg.sender` equivalent in ethereum.

<!-- What problem does this proposal address? -->

<!-- If someone only reads this far, what do you want them to know? -->


## Specification

Given two programs: token.aleo & escrow.aleo

```
program token.aleo;
mapping balances:
owner as address.public;
amount as u64.public;
function transfer:
input r0 as address.private;
input r1 as u64.private;
finalize self.caller r0 r1;
finalize transfer:
input r0 as address.public;
input r1 as address.public;
input r2 as u64.public;
decrement balances[r0] by r2;
increment balances[r1] by r2;
function transfer_program:
input r0 as address.private;
input r1 as u64.private;
finalize self.parent r0 r1;
finalize transfer_program:
input r0 as address.public;
input r1 as address.public;
input r2 as u64.public;
decrement balances[r0] by r2;
increment balances[r1] by r2;
function get_balance:
input r0 as address.private;
cast balances[r0] into r1 as u64;
output r1 as u64;
```

```
import token_one.aleo; // can be copy-pasted from token.aleo
import token_two.aleo; // can be copy-pasted from token.aleo
program amm.aleo;
mapping shares:
owner as address.public;
amount as u64.public;
function deposit_token_two:
input r0 as u64.private;
call token_two.aleo/transfer swap.aleo r0; // Deposit into pool
call token_two.aleo/get_balance swap.aleo into r1; // Get balance of pool
mul r0 4294967296u64 into r2; // Multiply deposit by 2^32 to prevent underflow
div r2 r1 into r3; // Divide deposit by total pool
finalize self.caller r0;
finalize deposit_token_two:
input r0 as address.public;
input r1 as u64.public;
increment shares[r0] by r1; // keep track of individual shares
increment shares[swap.aleo] by r1; // keep track of total shares
function withdraw_token_two:
input r0 as u64.private; // Shares to withdraw
call token_two.aleo/get_balance swap.aleo into r1; // Get balance of pool
cast shares[swap.aleo] into r2 as u64; // Total shares in the pool
// Get to transfer: shares * pool_balance / total_shares
mul r0 r1 into r3;
div r3 r2 into r4;
call token_two.aleo/transfer_program self.caller r4;
finalize self.caller r1;
finalize withdrawl_token_two:
input r0 as address.public;
input r1 as u64.public;
decrement shares[r0] by r1; // keep track of individual shares
decrement shares[swap.aleo] by r1; // keep track of total shares
function convert_token_one_to_token_two:
input r0 as u64.private;
mul r0 2u64 into r1; // Mocking a price of 1 token_one = 2 token_two
sub r1 1u64 into r2; // Charge some fee for conversion
call token_one.aleo/transfer swap.aleo r0;
call token_two.aleo/transfer_program self.caller r2;
finalize self.parent r0 r1;
```

<!-- Define key terminology here. -->
`self.parent` should default to the address of the calling program if there is one. If there isn't a calling program, it should result in the same address as `self.caller`.

<!-- Describe the architecture. -->
In our AMM example, we define toy token and amm programs to demonstrate how `self.parent` would be used to enable a program to own assets. In `token.aleo`, a user can transfer assets to a program (`amm.aleo`) by calling `transfer` and assets can be transferred out of the pool by calling `transfer_program`. Effectively, `self.parent` gives `amm.aleo` exclusive control to decide how its balance in `token.aleo` is decremented. In our case, we show how a toy AMM could enable pool deposits/lp share issuance, lp share redemption, and swaps.

<!-- Include process diagrams. -->

### Test Cases

```
program bar.aleo;
function get_bar:
output self.parent as address.public;
```

```
program foo.aleo;
function get_foo:
call bar.aleo/get_address into r0;
output r0 as address.public;
```

`aleo run get_foo` -> `address(foo.aleo)`
`aleo run get_bar` -> `address(self.caller)`



## Dependencies

<!-- Will this affect the Aleo PM, Aleo Explorer, or Aleo Studio? -->

<!-- Will this affect Aleo, Leo, snarkOS, snarkVM, or any other repositories? -->
This will impact snarkVM and everything that has snarkVM as a dependency.

### Backwards Compatibility

<!-- List all backwards incompatibilities and their severity. -->

<!-- How will the backwards incompatibilities be resolved? -->
As this is a new feature, no programs should be impacted by adding a new opcode.


## Security & Compliance

<!-- Outline any potential security concerns. -->

<!-- Does this proposal introduce regulatory risk? -->
There should be no regulatory concerns.


## References

<!-- List any links that would be helpful for context. -->
Explanation of [tx.origin vs msg.sender in etherem](https://ethereum.stackexchange.com/questions/1891/whats-the-difference-between-msg-sender-and-tx-origin)

0 comments on commit da3e3c6

Please sign in to comment.