Skip to content

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

pmarket contracts

Camada de contratos inteligentes de um prediction market brasileiro — mercados de previsão com liquidação em USDC na Polygon.

Produto no ar: pmarket.ai · Contratos em Polygon mainnet · 45 testes Foundry passando

Duas coisas verificáveis, cada uma por um caminho independente deste repositório: o produto responde em pmarket.ai, e os contratos abaixo respondem na Polygon. Este repositório é a camada on-chain — os contratos, os testes e a documentação de arquitetura do sistema.

Os contratos estão deployados e em operação em Polygon mainnet. Os endereços abaixo respondem hoje, e qualquer pessoa pode conferir sem depender deste repositório:

Contrato Endereço
ConditionalTokens 0x77D04D23…78451
CTFExchange 0x2640Ca91…A3004
UmaCtfAdapter 0x467eCaeb…9E79d
FeeModule 0x2F43Be22…5f3C6
cast code 0x2640Ca9114737f9384B4bc16928f066c92EA3004 --rpc-url https://polygon-rpc.com

Transações de criação, blocos, datas e método completo de verificação em DEPLOYMENTS.md.


O produto

pmarket.ai está no ar: mercados de previsão sobre política, economia, esportes e cripto, com curadoria voltada ao público brasileiro. Depósito por PIX, precificação por LMSR, indicadores econômicos integrados a fontes oficiais.

Os mercados em produção hoje liquidam off-chain. Os contratos deste repositório são a camada seguinte — a migração para liquidação on-chain, com o colateral em USDC e a resolução por oráculo otimista em vez de por decisão da plataforma. Estão deployados e sob governança, ainda não recebendo o volume de produção.

Ser explícito sobre isso importa: o que está provado on-chain é o deploy, não o volume. A linha do tempo mostra como cada peça chegou aqui.


Como funciona

Um mercado de previsão precisa resolver três problemas: representar apostas como ativos negociáveis, casar compradores com vendedores, e decidir quem ganhou. Cada contrato resolve um.

ConditionalTokens — o ativo

Cada mercado emite dois tokens ERC-1155: YES e NO. Depositar 1 USDC cunha 1 YES e 1 NO (splitPosition); devolver o par queima ambos e recupera 1 USDC (mergePosition). Quando o mercado resolve, o token vencedor vale 1 USDC e o perdedor vale zero.

Disso vem o invariante que sustenta todo o sistema:

1 YES + 1 NO = 1 USDC, sempre.

Enquanto ele valer, o contrato é solvente por construção — nunca há mais direito de resgate do que colateral depositado. É a primeira coisa que os testes verificam, por fuzzing.

CTFExchange — o casamento de ordens

Ordens são assinadas fora da cadeia via EIP-712 e casadas por um motor off-chain. Só a liquidação toca a blockchain. Ordem cancelada não custa gás.

O contrato reconhece três tipos de casamento:

  • Direct — quem quer comprar YES encontra quem quer vender YES.
  • Minting — um quer YES, outro quer NO. Nenhum dos dois precisa existir ainda: o contrato cunha o par a partir de USDC.
  • Merging — um vende YES, outro vende NO. O par é queimado de volta em USDC.

Os dois últimos são o que dá liquidez a um mercado novo, sem book. Não é preciso haver contraparte para o mesmo lado — basta haver contraparte para o lado oposto.

Cancelamento usa nonce incremental: incrementNonce invalida de uma vez todas as ordens assinadas anteriormente, fechando a janela de replay.

UmaCtfAdapter — a resolução

Quem decide o resultado é o UMA OptimisticOracleV2, não a plataforma. Um proponente posta caução afirmando o resultado. Abre-se janela de contestação. Sem contestação, o resultado é aceito; com contestação, escala para votação dos detentores de token UMA, e quem propôs errado perde a caução.

O adapter está sob Safe multisig 2-de-3, verificável on-chain:

cast call 0x467eCaebc56f352057b20cfb5eA5957cb629E79d "admin()(address)" \
  --rpc-url https://polygon-rpc.com

FeeModule — as taxas

Taxa aplicada sobre o lado vencedor na liquidação, com divisão programática entre operação e fundo de reserva. O teste de fuzz garante que a taxa calculada nunca excede o valor negociado.

NegRiskAdapter — mercados de múltiplos resultados

Para perguntas com mais de duas respostas (eleições, por exemplo), onde os resultados são mutuamente exclusivos e as probabilidades precisam somar 1.


Testes

45 testes Foundry, todos passando, incluindo fuzzing sobre as duas propriedades que não podem quebrar:

Suíte Testes
ConditionalTokens.t.sol 18
UmaCtfAdapter.t.sol 10
CTFExchange.t.sol 9
NegRiskAdapter.t.sol 8
forge test -vv
forge test --match-test testFuzz -vvv   # só os invariantes

Os dois testes de propriedade:

  • testFuzz_invariant_yesNoPlusMeansOneUSDC — o invariante do colateral, sob entradas aleatórias.
  • testFuzz_calculateFee_neverExceedsAmount — taxa nunca maior que o principal.

Rodando localmente

Requer Foundry.

git clone --recursive https://github.com/lfpossebon/pmarket-contracts.git
cd pmarket-contracts
forge build
forge test

As dependências são submódulos com commit fixado, então o build é reprodutível. A do OpenZeppelin está travada em v5.0.2 de propósito — é a usada no deploy de mainnet, e os caminhos de import mudaram entre as majors do OZ. Se você já clonou sem --recursive:

git submodule update --init --recursive

Para deploy, copie .env.example para .env e preencha. Os scripts em script/ leem todas as chaves de variáveis de ambiente — nenhuma credencial está embutida no código.


Estrutura

src/
  ConditionalTokens.sol      # ERC-1155 YES/NO, split/merge/redeem
  CTFExchange.sol            # casamento EIP-712, três tipos de match
  UmaCtfAdapter.sol          # resolução via UMA OOv2
  NegRiskAdapter.sol         # mercados de múltiplos resultados
  FeeModule.sol              # taxas e divisão
  interfaces/                # IConditionalTokens, IOptimisticOracleV2
  libraries/                 # OrderStructs (EIP-712), CalculatorHelper
test/                        # 45 testes Foundry
script/                      # deploy, criação de mercado, E2E
docs/                        # documentação de arquitetura do sistema

A pasta docs/ traz a arquitetura da plataforma inteira, não só dos contratos: exchange, ciclo de ordens, oráculo, carteiras, modelos de mercado e o dicionário de dados.


Créditos e proveniência

Esta implementação deriva de trabalho open-source de terceiros, e é importante ser explícito sobre o que é original e o que não é:

  • ConditionalTokens deriva do Gnosis Conditional Tokens Framework — LGPL-3.0.
  • CTFExchange, UmaCtfAdapter e NegRiskAdapter derivam dos contratos da Polymarket — MIT.
  • FeeModule e as modificações dos demais são originais deste projeto.

A arquitetura de referência é a da Polymarket. O trabalho aqui foi adaptá-la ao contexto brasileiro, não inventá-la.


Limitações

  • Sem auditoria externa. Os contratos de origem são auditados; as modificações desta implementação não passaram por auditoria independente.
  • Mainnet tem deploy, não volume. O ciclo completo de mercado — criação, negociação, resolução e resgate — foi exercitado em testnet Amoy. Os mercados em produção operam hoje no modelo off-chain da plataforma.

Linha do tempo da construção e decisões de arquitetura em STATUS.md.


Licença

MIT, com exceção de src/ConditionalTokens.sol, que permanece LGPL-3.0 por derivação. Ver LICENSE.

About

Camada de contratos de um prediction market brasileiro — deployados e verificáveis em Polygon mainnet. CTF, CLOB com ordens EIP-712 e resolução por oráculo otimista UMA.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages