bitcoin-sv / sol2scrypt

Solidity to sCrypt Transplier
BSD 3-Clause "New" or "Revised" License
1 stars 0 forks source link

Master Task: transpiler #1

Open xhliu opened 2 years ago

xhliu commented 2 years ago

solang: Solidity Compiler for Solana,

Must read: https://tomassetti.me/how-to-write-a-transpiler/ src lang -> src AST ->[ Intermediate AST ->] dst AST -> dst lang

https://thorny.io/blog/how-and-why-i-wrote-a-transpiler https://engineering.mongodb.com/post/transpiling-between-any-programming-languages-part-1 https://daily.dev/blog/transpilers-how-they-work#strongwhat-are-transpilersstrong https://medium.com/trymito/minimum-effort-transpiler-writing-a-passable-programming-language-in-half-a-day-ae8da585b252

Open-source transpilers: https://awesomeopensource.com/projects/transpiler

xhliu commented 2 years ago

Solidity Transpilers

Code samples

https://github.com/madfish-solutions/sol2ligo Solidity contract --> Zolidity contract: https://github.com/EYBlockchain/starlight detailed doc Transpiler from Solidity 4.25 to Solidity 5.0: https://github.com/solsuite/solfix https://github.com/polkafoundry/solidity2js

Solidity to Ligo transpiler

https://madfish-solutions.github.io/sol2ligo/ https://github.com/madfish-solutions/sol2ligo/wiki https://medium.com/coinmonks/solidity-to-ligo-transpiler-981ac35a7297 https://medium.com/madfish-solutions/what-is-a-transpiler-47beac592848 https://xtz.news/adoption/sol2ligo-by-madfish-solutions-simplify-converting-ethereum-solidity-contracts-to-tezos-ligo-contracts/

Others

xhliu commented 2 years ago

Reusable parser

In Haskell

  1. https://github.com/gordonpace/contractLarva/blob/master/src/Solidity/Parsing.hs main.pdf

solidity-cfg-builder is developed in Haskell, utilising a Solidity syntax parser used in the runtime verification tool for Solidity contractLarva. https://github.com/shaunazzopardi/solidity-cfg-builder/blob/master/src/CFG/Parsing.hs#L11-L12

2. A partial parser https://github.com/WePesa/solidity-abi/tree/master/parse

3. https://github.com/shaunazzopardi/solidity-partial-evaluator/blob/master/Solidity/Parsing.hs https://github.com/shaunazzopardi/ethereuem-runtime-verification/blob/master/src/Solidity/Parsing.hs

In other languages https://github.com/search?q=solidity+parser&type=repositories https://github.com/federicobond/solidity-parser-antlr https://github.com/ConsenSysMesh/solidity-parser

xhliu commented 2 years ago

Challenges

https://github.com/madfish-solutions/sol2ligo/wiki/Known-issues

warp: it doesn't use things like msg.sender or msg.value

Subset of solidity

xhliu commented 2 years ago

msg.sender

PubKey owner;

public function mint(Sig sig) {
  checkSig(sig, this.owner);

}

public function transfer(Sig sig, PubKey sender, PubKey receiver) {
  checkSig(sig, sender);
}
xhliu commented 2 years ago

block.timestamp

msg.value

xhliu commented 2 years ago

Milestone 1

https://github.com/madfish-solutions/sol2ligo/blob/pretty-ligo/solidity_samples/ethereum/solidity-examples/src/math/ExactMath.sol

Milestone 2

Most popular contracts: ERC20 token: https://ethereum.org/en/developers/tutorials/understand-the-erc-20-token-smart-contract/ https://github.com/ConsenSys/Tokens/blob/master/contracts/eip20/EIP20.sol https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol

NFT

Shibi https://etherscan.io/address/0x95ad61b0a150d79219dcf64e1e6cc01f0b64c4ce#code

Swap

Milestone 3

MakerDAO

xhliu commented 2 years ago
pragma solidity ^0.6.0;

contract ERC20 {

    string public constant name = "ERC20Basic";
    string public constant symbol = "ERC";
    uint8 public constant decimals = 18;

    event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
    event Transfer(address indexed from, address indexed to, uint tokens);

    mapping(address => uint256) balances;

    mapping(address => mapping (address => uint256)) allowed;

    uint256 totalSupply_;

   constructor(uint256 total) public {
    totalSupply_ = total;
    balances[msg.sender] = totalSupply_;
    }

    function totalSupply() public override view returns (uint256) {
    return totalSupply_;
    }

    function balanceOf(address tokenOwner) public override view returns (uint256) {
        return balances[tokenOwner];
    }

    function transfer(address receiver, uint256 numTokens) public override returns (bool) {
        require(numTokens <= balances[msg.sender]);
        balances[msg.sender] = balances[msg.sender].sub(numTokens);
        balances[receiver] = balances[receiver].add(numTokens);
        emit Transfer(msg.sender, receiver, numTokens);
        return true;
    }

    function approve(address delegate, uint256 numTokens) public override returns (bool) {
        allowed[msg.sender][delegate] = numTokens;
        emit Approval(msg.sender, delegate, numTokens);
        return true;
    }

    function allowance(address owner, address delegate) public override view returns (uint) {
        return allowed[owner][delegate];
    }

    function transferFrom(address owner, address buyer, uint256 numTokens) public override returns (bool) {
        require(numTokens <= balances[owner]);
        require(numTokens <= allowed[owner][msg.sender]);

        balances[owner] = balances[owner].sub(numTokens);
        allowed[owner][msg.sender] = allowed[owner][msg.sender].sub(numTokens);
        balances[buyer] = balances[buyer].add(numTokens);
        emit Transfer(owner, buyer, numTokens);
        return true;
    }
}

library SafeMath {
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
      assert(b <= a);
      return a - b;
    }

    function add(uint256 a, uint256 b) internal pure returns (uint256) {
      uint256 c = a + b;
      assert(c >= a);
      return c;
    }
}

=>

// struct PubKeyPair {
//     PubKey owner;
//     PubKey delegate;
// }

// ERC20 in sCrypt
contract ERC20 {

    static const bytes name = b'45524332304261736963'; //"ERC20Basic";
    static const bytes symbol = b'455243'; //"ERC";
    static const int decimals = 18;

    @state
    HashedMap<PubKey, int> balances;

    // HashedMap<PubKeyPair, int> allowed;

    int totalSupply_;

    constructor(int total, PubKey issuer, int idx) {
        this.totalSupply_ = total;
        this.balances.set(issuer, total, idx);
    }

    function totalSupply() : int {
        return this.totalSupply_;
    }

    function balanceOf(PubKey tokenOwner, int balance, int idx) : bool {
        return this.balances.canGet(tokenOwner, balance, idx);
    }

    public function transfer(PubKey sender, Sig sig, PubKey receiver, int numTokens, int senderBalance, int receiverBalance, int senderIdx, int receiverIdx) {
        require(checkSig(sender, sig));

        require(this.balances.canGet(sender, senderBalance, senderIdx));
        require(numTokens <= senderBalance);
        this.balances.set(sender, senderBalance - numTokens, senderIdx);
        this.balances.set(receiver, receiverBalance + numTokens, receiverIdx);
        require(true);
    }

    // function approve(PubKey delegate, int numTokens) public override returns (bool) {
    //     allowed[sender][delegate] = numTokens;
    //     emit Approval(sender, delegate, numTokens);
    //     return true;
    // }

    // function allowance(PubKey owner, PubKey delegate) public override view returns (int) {
    //     return allowed[owner][delegate];
    // }

    // function transferFrom(PubKey owner, PubKey buyer, int numTokens) public override returns (bool) {
    //     require(numTokens <= balances[owner]);
    //     require(numTokens <= allowed[owner][sender]);

    //     balances[owner] = balances[owner].sub(numTokens);
    //     allowed[owner][sender] = allowed[owner][sender].sub(numTokens);
    //     balances[buyer] = balances[buyer].add(numTokens);
    //     emit Transfer(owner, buyer, numTokens);
    //     return true;
    // }
}