{"id":42165999,"url":"https://github.com/nibiruchain/coded-estate-evm","last_synced_at":"2026-01-26T21:02:41.088Z","repository":{"id":334265324,"uuid":"1140216623","full_name":"NibiruChain/coded-estate-evm","owner":"NibiruChain","description":"Solidity and EVM interface contracts for Coded Estate rental app","archived":false,"fork":false,"pushed_at":"2026-01-23T18:27:01.000Z","size":78,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-24T08:40:22.785Z","etag":null,"topics":["ethereum","ethers","evm","nibiru","smart-contracts","solidity"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/NibiruChain.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-01-23T01:23:40.000Z","updated_at":"2026-01-23T18:29:25.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/NibiruChain/coded-estate-evm","commit_stats":null,"previous_names":["nibiruchain/coded-estate-evm"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/NibiruChain/coded-estate-evm","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NibiruChain%2Fcoded-estate-evm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NibiruChain%2Fcoded-estate-evm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NibiruChain%2Fcoded-estate-evm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NibiruChain%2Fcoded-estate-evm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/NibiruChain","download_url":"https://codeload.github.com/NibiruChain/coded-estate-evm/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NibiruChain%2Fcoded-estate-evm/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28788080,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-26T13:55:28.044Z","status":"ssl_error","status_checked_at":"2026-01-26T13:55:26.068Z","response_time":59,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ethereum","ethers","evm","nibiru","smart-contracts","solidity"],"created_at":"2026-01-26T21:02:40.052Z","updated_at":"2026-01-26T21:02:41.070Z","avatar_url":"https://github.com/NibiruChain.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# CodedEstate EVM Interface\n\nThis repo contains a Solidity \"gateway\" contract that lets EVM callers execute CodedEstate rental actions implemented as a CosmWasm contract on Nibiru.\n\nAt a high level:\n\n1. The frontend constructs a CosmWasm `ExecuteMsg` as JSON.\n2. The frontend UTF-8 encodes that JSON to `bytes`.\n3. The Solidity gateway forwards those bytes to the Nibiru Wasm precompile (`IWasm.execute`).\n4. For actions that require payment, the gateway can (optionally) convert ERC20 -\u003e bank coins using the FunToken precompile, then attach bank-denom funds to the Wasm execution.\n\nThe result is a stable EVM ABI while the Wasm contract evolves. Most functions accept `bytes wasmMsgExecute` so the schema stays on the Wasm side.\n\n- [Building the Contracts](#building-the-contracts)\n- [Repository layout](#repository-layout)\n- [Core dependencies (Nibiru precompiles)](#core-dependencies-nibiru-precompiles)\n- [Contract: `CodedEstateEvmInterface`](#contract-codedestateevminterface)\n  - [What the contract stores](#what-the-contract-stores)\n  - [Timelocked address updates](#timelocked-address-updates)\n  - [Calling pattern](#calling-pattern)\n- [Action catalog (Rust variant -\u003e JSON -\u003e Solidity call)](#action-catalog-rust-variant---json---solidity-call)\n- [TypeScript support (`evmImpl.ts`)](#typescript-support-evmimplts)\n\n## Building the Contracts\n\n1 -  [Install bun](https://bun.com/docs/installation). \n\n2 - Run `nvm use`.\n\n3 - Install `just` to run project-specific commands.\n\n```bash\ncargo install just\n```\n\n**Compile Solidity contracts**. \n```bash\njust build\n```\n\nRef: [github.com/casey/just](https://github.com/casey/just)\n\n## Repository layout\n\n- `contracts/CodedEstateEvmInterface.sol`\n  - The gateway contract deployed on Nibiru EVM.\n- `evmImpl.ts`\n  - TypeScript types for the known JSON message shapes and a helper for encoding messages.\n- `hardhat.config.js`, `package.json`, `justfile`\n  - Build tooling for compiling the Solidity contract and generating artifacts.\n\n\n---\n\n## Core dependencies (Nibiru precompiles)\n\nThis interface relies on Nibiru's precompiled contracts:\n\n- `IWasm` (`WASM_PRECOMPILE_ADDRESS = 0x...0802`)\n  - Executes a Wasm contract's `ExecuteMsg` given JSON bytes and optional funds.\n- `IFunToken` (`FUNTOKEN_PRECOMPILE_ADDRESS = 0x...0800`)\n  - Resolves EVM \u003c-\u003e bech32 address pairs and converts ERC20 \u003c-\u003e bank-denom balances.\n\nYou do not call these directly from the frontend. The gateway delegates to them internally.\n\n---\n\n## Contract: `CodedEstateEvmInterface`\n\n`CodedEstateEvmInterface` is a thin wrapper around `IWasm.execute`, plus a convenience function for \"reservation with payment\".\n\n### What the contract stores\n\n- `rentalContractAddress` (string, bech32)\n  - The current Wasm contract address that receives `ExecuteMsg`.\n- Timelocked address update fields:\n  - `timelockDelay`\n  - `pendingRentalContractAddress`\n  - `changeEffectiveTimestamp`\n\n### Timelocked address updates\n\nThe owner can rotate the underlying Wasm rental contract address with a delay:\n\n- `proposeNewRentalContractAddress(string newAddress)`\n  - Sets `pendingRentalContractAddress` and schedules an effective timestamp.\n- `executeNewRentalContractAddress()`\n  - After the timelock expires, makes the new address active.\n\nThis pattern mirrors the PerpVault EVM interface pattern.\n\n### Calling pattern\n\n#### Encode a Wasm execute message\n\nEvery CodedEstate action is expressed as a JSON object with a single top-level key\n(the execute message name) and a payload object.\n\nEncode it like this:\n\n```ts\nimport { ethers } from \"ethers\"\n\nconst wasmMsg = { /* ... */ }\nconst wasmMsgBytes = ethers.toUtf8Bytes(JSON.stringify(wasmMsg))\n```\n\nOr use the helper in `evmImpl.ts`:\n\n```ts\nimport { encodeRentalMessage } from \"./evmImpl\"\n\nconst wasmMsgBytes = encodeRentalMessage(wasmMsg)\n```\n\n#### Execute without funds\n\nUse this for actions that do not require payment:\n\n- `executeRental(bytes wasmMsgExecute)`\n\n#### Execute with funds\n\nUse this when the Wasm contract expects bank-denom funds:\n\n- `executeRentalWithFunds(bytes wasmMsgExecute, BankCoin[] funds)`\n\n#### Reservation with payment (special wrapper)\n\nReservations require payment to be attached as funds. Use:\n\n- `setReservationForShortTerm(\n    bytes wasmMsgExecute,\n    string paymentDenom,\n    uint256 paymentAmountBank,\n    address paymentErc20,\n    uint256 useErc20Amount\n  )`\n\nWhat it does:\n\n- Requires `paymentAmountBank \u003e 0`.\n- If `useErc20Amount \u003e 0`, it calls `sendToBank(paymentErc20, useErc20Amount, callerBech32)`.\n- If `paymentDenom` is empty, it derives the bank denom from `paymentErc20`.\n- Then it calls `executeRentalWithFunds` with exactly one `BankCoin { denom, amount }`.\n\nThis keeps the Wasm message payload focused on rental logic while the gateway handles payment mechanics.\n\n---\n\n## Action catalog (Rust variant -\u003e JSON -\u003e Solidity call)\n\nBelow, \"Rust variant\" names are the expected `ExecuteMsg` variants based on the README naming convention (`#[serde(rename_all = \"snake_case\")]`). The wire truth is the JSON key.\n\n- [1) Mint NFT](#1-mint-nft)\n- [2) List property for short-term rental](#2-list-property-for-short-term-rental)\n- [3) Unlist property](#3-unlist-property)\n- [4) Create reservation (requires funds)](#4-create-reservation-requires-funds)\n- [5) Approve reservation](#5-approve-reservation)\n- [6) Reject reservation (opaque)](#6-reject-reservation-opaque)\n- [7) Cancel reservation (unapproved, opaque)](#7-cancel-reservation-unapproved-opaque)\n- [8) Cancel rental (approved, opaque)](#8-cancel-rental-approved-opaque)\n- [9) Finalize rental (opaque)](#9-finalize-rental-opaque)\n\n### 1) Mint NFT\n\n**Rust variant (expected)**: `ExecuteMsg::Mint { token_id, owner, token_uri, extension }`\n\n**Wire JSON**\n\n```json\n{\n  \"mint\": {\n    \"token_id\": \"prop_123\",\n    \"owner\": \"nibi1...\",\n    \"token_uri\": \"ipfs://cid\",\n    \"extension\": {}\n  }\n}\n```\n\n**Solidity call**\n\n- `executeRental(wasmMsgBytes)`\n\n### 2) List property for short-term rental\n\n**Rust variant (expected)**: `ExecuteMsg::SetListForShortTermRental { ... }`\n\n**Wire JSON**\n\n```json\n{\n  \"set_list_for_short_term_rental\": {\n    \"token_id\": \"prop_123\",\n    \"denom\": \"uusdc\",\n    \"price_per_day\": \"2500000\",\n    \"auto_approve\": false,\n    \"available_period\": [],\n    \"minimum_stay\": \"2\",\n    \"cancellation\": [{ \"deadline\": \"86400\", \"percentage\": \"50\" }]\n  }\n}\n```\n\n**Solidity call**\n\n- `executeRental(wasmMsgBytes)`\n\n### 3) Unlist property\n\n**Rust variant (expected)**: `ExecuteMsg::SetUnlistForShorttermRental { token_id }`\n\n**Wire JSON**\n\n```json\n{ \"set_unlist_for_shortterm_rental\": { \"token_id\": \"prop_123\" } }\n```\n\n**Solidity call**\n\n- `executeRental(wasmMsgBytes)`\n\n### 4) Create reservation (requires funds)\n\n**Rust variant (expected)**: `ExecuteMsg::SetReservationForShortTerm { token_id, renting_period, guests }`\n\n**Wire JSON**\n\n```json\n{\n  \"set_reservation_for_short_term\": {\n    \"token_id\": \"prop_123\",\n    \"renting_period\": [\"1706745600\", \"1707004800\"],\n    \"guests\": \"2\"\n  }\n}\n```\n\n**Solidity call**\n\nUse `setReservationForShortTerm(...)` so the gateway attaches payment funds.\n\nExample:\n\n```ts\nawait codedEstateEvm.setReservationForShortTerm(\n  wasmMsgBytes,\n  \"uusdc\",\n  5_000_000n,         // bank units sent as funds\n  ethers.ZeroAddress,  // paymentErc20 (optional)\n  0n,                  // useErc20Amount (optional)\n  overrides\n)\n```\n\nIf paying via ERC20 first:\n\n```ts\nawait codedEstateEvm.setReservationForShortTerm(\n  wasmMsgBytes,\n  \"uusdc\",            // or \"\" to derive from paymentErc20\n  5_000_000n,\n  usdcErc20Address,\n  useErc20Amount,\n  overrides\n)\n```\n\n### 5) Approve reservation\n\n**Rust variant (expected)**: `ExecuteMsg::SetApproveForShortTerm { token_id, traveler, renting_period }`\n\n**Wire JSON**\n\n```json\n{\n  \"set_approve_for_short_term\": {\n    \"token_id\": \"prop_123\",\n    \"traveler\": \"nibi1...\",\n    \"renting_period\": [\"1706745600\", \"1707004800\"]\n  }\n}\n```\n\n**Solidity call**\n\n- `executeRental(wasmMsgBytes)`\n\n### 6) Reject reservation (opaque)\n\n**Wire key**: `reject_reservation_for_shortterm`\n\nThe README names this message but does not specify field-level JSON. Keep the payload opaque and send it through:\n\n- `executeRental(wasmMsgBytes)`\n\n### 7) Cancel reservation (unapproved, opaque)\n\n**Wire key**: `cancel_reservation_for_shortterm`\n\nSame situation as above:\n\n- `executeRental(wasmMsgBytes)`\n\n### 8) Cancel rental (approved, opaque)\n\n**Wire key**: `cancel_rental_for_shortterm`\n\nSame situation:\n\n- `executeRental(wasmMsgBytes)`\n\n### 9) Finalize rental (opaque)\n\n**Wire key**: `finalize_short_term_rental`\n\nSame situation:\n\n- `executeRental(wasmMsgBytes)`\n\n---\n\n## TypeScript support (`evmImpl.ts`)\n\n`evmImpl.ts` provides:\n\n- Primitive types (bech32, ipfs URIs, string-encoded integers).\n- Strict types for message shapes that are explicitly defined in the README.\n- Opaque placeholders for message names that exist but lack field-level schema.\n- `encodeRentalMessage(msg)` helper: `ethers.toUtf8Bytes(JSON.stringify(msg))`.\n\nThe intent is: type what we know, avoid guessing what we do not.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnibiruchain%2Fcoded-estate-evm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnibiruchain%2Fcoded-estate-evm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnibiruchain%2Fcoded-estate-evm/lists"}