Skip to content

Instantly share code, notes, and snippets.

@Turupawn
Last active May 18, 2024 05:19
Show Gist options
  • Save Turupawn/9c2ce8e3de4ac92fb7f99552acb74ff5 to your computer and use it in GitHub Desktop.
Save Turupawn/9c2ce8e3de4ac92fb7f99552acb74ff5 to your computer and use it in GitHub Desktop.
Scroll Workshop
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract SimpleToken is ERC20 {
constructor() ERC20("My Token", "MTK") {
uint initialSupply = 2_000_000_000;
_mint(msg.sender, initialSupply * 1 ether);
}
}

Install foundry

curl -L https://foundry.paradigm.xyz | bash
foundryup

Create new project

forge init hello_foundry
cd hello_foundry/
forge build

Deploy

forge create src/Counter.sol:Counter --rpc-url=https://sepolia-rpc.scroll.io/ --legacy --private-key YOURPRIVATEKEY

Verify

forge verify-contract YOURCONTRACTADDRESS src/Counter.sol:Counter --verifier-url https://api-sepolia.scrollscan.com/api --etherscan-api-key SCROLLSCANAPIKEY

1. Contract

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.13;

contract Hello
{
    string public hello = "Hola mundo!";
    uint public count;
    address public last_writer;

    function setHello(string memory _hello) public
    {
        hello = _hello;
        count += 1;
        last_writer = msg.sender;
    }
}

2. Dapp

https://github.com/FilosofiaCodigo/Web3TemplateV2

//////////////////////////////////////////////////////////////////
//EAS
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import { IEAS, AttestationRequest, AttestationRequestData, RevocationRequest, RevocationRequestData } from "@ethereum-attestation-service/eas-contracts/contracts/IEAS.sol";
import { NO_EXPIRATION_TIME, EMPTY_UID } from "@ethereum-attestation-service/eas-contracts/contracts/Common.sol";
contract EASDemo
{
address easAddress = 0xaEF4103A04090071165F78D45D83A0C0782c2B2a;
bytes32 schema = 0x27d06e3659317e9a4f8154d1e849eb53d43d91fb4f219884d1684f86d797804a;
// check at https://scroll-sepolia.easscan.org/schema/view/0x27d06e3659317e9a4f8154d1e849eb53d43d91fb4f219884d1684f86d797804a
function sendIsFriend(address to, bool isFriend) public returns(bytes32)
{
return IEAS(easAddress).attest(
AttestationRequest({
schema: schema,
data: AttestationRequestData({
recipient: to,
expirationTime: NO_EXPIRATION_TIME,
revocable: false,
refUID: EMPTY_UID,
data: abi.encode(isFriend),
value: 0 // No value/ETH
})
})
);
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
library DataTypes {
struct ReserveConfigurationMap {
uint256 data;
}
struct ReserveData {
ReserveConfigurationMap configuration;
uint128 liquidityIndex;
uint128 currentLiquidityRate;
uint128 variableBorrowIndex;
uint128 currentVariableBorrowRate;
uint128 currentStableBorrowRate;
uint40 lastUpdateTimestamp;
uint16 id;
address aTokenAddress;
address stableDebtTokenAddress;
address variableDebtTokenAddress;
address interestRateStrategyAddress;
uint128 accruedToTreasury;
uint128 unbacked;
uint128 isolationModeTotalDebt;
}
}
interface IPool {
function borrow(
address asset,
uint256 amount,
uint256 interestRateMode, // 1 for Stable, 2 for Variable
uint16 referralCode,
address onBehalfOf) external;
function supply(
address asset,
uint256 amount,
address onBehalfOf,
uint16 referralCode) external;
function withdraw(
address asset,
uint256 amount,
address to) external returns (uint256);
function getReserveData(
address asset) external view returns (DataTypes.ReserveData memory);
}
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 value) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 value) external returns (bool);
function transferFrom(address from, address to, uint256 value) external returns (bool);
}
contract AaveLender {
address public immutable AAVE_POOL_ADDRESS;
address public immutable STAKED_TOKEN_ADDRESS;
address public immutable ATOKEN_ADDRESS;
address public immutable OWNER;
mapping(address account => uint amount) public stakeByAccount;
uint public totalStake;
// Ejemplo en Scroll Sepolia
// Pool Address
// 0x48914C788295b5db23aF2b5F0B3BE775C4eA9440
// DAI
// 0x7984E363c38b590bB4CA35aEd5133Ef2c6619C40
// check at https://app.aave.com/
constructor(address aavePoolAddress, address stakedTokenAddress) {
AAVE_POOL_ADDRESS = aavePoolAddress;
STAKED_TOKEN_ADDRESS = stakedTokenAddress;
OWNER = msg.sender;
ATOKEN_ADDRESS = IPool(aavePoolAddress).getReserveData(stakedTokenAddress).aTokenAddress;
}
function stake(uint amount) public {
totalStake += amount;
stakeByAccount[msg.sender] += amount;
IERC20(STAKED_TOKEN_ADDRESS).transferFrom(msg.sender, address(this), amount);
IERC20(STAKED_TOKEN_ADDRESS).approve(AAVE_POOL_ADDRESS, amount);
IPool(AAVE_POOL_ADDRESS).supply(
STAKED_TOKEN_ADDRESS,
amount,
address(this),
0);
}
function unstake(uint amount) public {
require(amount <= stakeByAccount[msg.sender], "Not enough stake");
totalStake -= amount;
stakeByAccount[msg.sender] -= amount;
IPool(AAVE_POOL_ADDRESS).withdraw(
STAKED_TOKEN_ADDRESS,
amount,
msg.sender
);
}
function yieldEarned() public view returns(uint){
return IERC20(ATOKEN_ADDRESS).balanceOf(address(this)) - totalStake;
}
function withdraw(uint amount) public {
require(msg.sender == OWNER, "Sender is not owner");
require(amount <= yieldEarned(), "Maximum withdraw exceeded");
IPool(AAVE_POOL_ADDRESS).withdraw(
STAKED_TOKEN_ADDRESS,
amount,
msg.sender
);
}
}

Instalación

En Linux

mkdir -p $HOME/.nargo/bin && \
curl -o $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.22.0/nargo-x86_64-unknown-linux-gnu.tar.gz && \
tar -xvf $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -C $HOME/.nargo/bin/ && \
echo -e '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.bashrc && \
source ~/.bashrc

En MacOs Apple Silicon

mkdir -p $HOME/.nargo/bin && \
curl -o $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.22.0/nargo-aarch64-apple-darwin.tar.gz && \
tar -xvf $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \
echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \
source ~/.zshrc

En MacOs Intel

mkdir -p $HOME/.nargo/bin && \
curl -o $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.22.0/nargo-x86_64-apple-darwin.tar.gz && \
tar -xvf $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \
echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \
source ~/.zshrc

Genera una prueba

Genera un nuevo proyecto de noir y prepáralo para recibir parámetros para el proveing.

nargo new hello_world
cd hello_world
nargo check

Ahora pon los inputs en Prover.toml y genera la prueba.

Prover.toml

x = "1"
y = "2"
nargo prove

La prueba ahora está ubicada en proofs/hello_world.proof.

Verifica la prueba

Genera un verificador en Solidity.

nargo codegen-verifier

El contrato verificador ahora está ubicado en contract/hello_world/plonk_vk.sol. Deplóyalo y envía su address como parámetro del siguiente contrato con lógica personalizada.

// SPDX-License-Identifier: MIT

pragma solidity >=0.7.0 <0.9.0;

interface INoirVerifier {
    function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool);
}

contract NoirCustomLogic {
    INoirVerifier noirVerifier;
    uint public publicInput;
    uint public verifyCount;

    constructor(address noirVeriferAddress) {
        noirVerifier = INoirVerifier(noirVeriferAddress);
    }

    function sendProof(bytes calldata _proof, bytes32[] calldata _publicInputs) public {
        // ZK verification
        noirVerifier.verify(_proof, _publicInputs);

        // Your custom logic
        publicInput = uint(_publicInputs[0]);
        verifyCount+=1;
    }
}

De esta manera puedes demostrar on-chain que tienes el conocimiento de a, tal que a!=b, esto sin revelar a que es un parámetros privado. Esta misma arquitectura puede aplicar en proyectos más avanzados donde puedes anonimizar, por ejemplo, al usuario que ejecutó una transacción o a el monto de una transacción.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment