Deploy contratos

Deploy contratos

Ruby Chain corre EVM estándar (no hay opcodes custom). Cualquier contrato que funcione en Ethereum funciona acá.

Setup mínimo (Hardhat)

mkdir my-ruby-project && cd my-ruby-project
npm init -y
npm install --save-dev hardhat @nomicfoundation/hardhat-toolbox @openzeppelin/contracts dotenv
npx hardhat init  # → "Create a TypeScript project"

Editá hardhat.config.ts:

import "@nomicfoundation/hardhat-toolbox";
import { HardhatUserConfig } from "hardhat/config";
import * as dotenv from "dotenv";
dotenv.config();
 
const config: HardhatUserConfig = {
  solidity: {
    version: "0.8.24",
    settings: { optimizer: { enabled: true, runs: 200 }, evmVersion: "cancun" },
  },
  networks: {
    ruby: {
      url: "https://rpc.ruby.testnet.finetry.win",
      chainId: 1810,
      accounts: [process.env.PRIVATE_KEY!],
    },
  },
};
export default config;

.env:

PRIVATE_KEY=0x...   # tu wallet con RUBY del faucet

Deployar un ERC-20

contracts/MyToken.sol:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
 
contract MyToken is ERC20 {
  constructor() ERC20("My Token", "MYT") {
    _mint(msg.sender, 1_000_000 * 10**18);
  }
}

scripts/deploy.ts:

import { ethers } from "hardhat";
 
async function main() {
  const T = await ethers.getContractFactory("MyToken");
  const t = await T.deploy();
  await t.waitForDeployment();
  console.log("MyToken at:", await t.getAddress());
}
main().catch((e) => { console.error(e); process.exit(1); });
npx hardhat compile
npx hardhat run scripts/deploy.ts --network ruby

Foundry

forge init my-ruby
cd my-ruby
forge install OpenZeppelin/openzeppelin-contracts
 
cat > .env <<EOF
RPC=https://rpc.ruby.testnet.finetry.win
PK=0x...
EOF
source .env
 
forge create --rpc-url $RPC --private-key $PK src/MyToken.sol:MyToken

Verificación en Blockscout

Blockscout v8 soporta verificación standard solc-input + flattened.

Vía CLI:

npx hardhat verify --network ruby <CONTRACT_ADDRESS>

Vía web:

  1. Andá a https://explorer.ruby.testnet.finetry.win/address/<CONTRACT>/contract-verification
  2. Pegá source + selecciona compiler version
  3. Submit

Cosas a considerar

  • Gas precio: la chain corre con base fee dinámico EIP-1559. Casi siempre es de gwei microscópicos. No te preocupes por gas optimization extrema en testnet.
  • Block size limit: 60M gas. Suficiente para casi cualquier contrato razonable.
  • Hardforks activos: todos hasta Cancun (incluye blob txs en L1, EIP-4844). Tu Solidity puede usar mcopy y similares.
  • Predeploys: usá los 0x4200...XXXX para interactuar con el sistema OP Stack (bridge, fee vaults, etc.).

Patterns útiles

Receive deposits desde L1

Si tu contrato L1 quiere mandar mensajes/value a L2:

// L1 side
import { IL1CrossDomainMessenger } from "...";
IL1CrossDomainMessenger(L1_MESSENGER).sendMessage(
  L2_TARGET,
  abi.encodeWithSignature("doStuff(bytes)", data),
  200_000  // gasLimit on L2
);
// L2 side
import { IL2CrossDomainMessenger } from "...";
modifier onlyFromL1Sender(address l1Sender) {
  IL2CrossDomainMessenger m = IL2CrossDomainMessenger(0x4200...0007);
  require(msg.sender == address(m), "not messenger");
  require(m.xDomainMessageSender() == l1Sender, "wrong L1 sender");
  _;
}
function doStuff(bytes memory data) external onlyFromL1Sender(MY_L1_CONTROLLER) { ... }

Más patterns en docs.optimism.io (opens in a new tab).