CULTIVA IA Servicio de Seguridad · Evaluador de Madurez de Codigo

Code Maturity Assessment — NutriPaw NPAWS Protocol

Proyecto:NutriPaw Token Staking & Rewards
Plataforma:Solidity 0.8.20 / Ethereum + Polygon
Fecha:16 junio 2026
Framework:Trail of Bits Code Maturity v0.1.0
1.7
/ 4.0
WEAK-MOD

Madurez Global: MODERADA-DEBIL

Solidity 0.8.20 DeFi · Staking Sin auditoria previa

El protocolo NPAWS presenta gaps criticos en aritmetica, descentralizacion y testing que deben resolverse antes de cualquier lanzamiento en mainnet. Las fortalezas radican en la estructura basica de contratos y en el uso de librerias estandar (OpenZeppelin). Se requieren mejoras sustanciales en 5 de las 9 categorias evaluadas.

Resumen Ejecutivo

▲ Top 3 Fortalezas

  • Solidity 0.8.20 con proteccion overflow nativa; uso de OpenZeppelin para controles de acceso (AccessControl + Ownable).
  • Separacion de contratos por responsabilidad (Staking / Rewards / Governance) con interfaces definidas.
  • Eventos emitidos para operaciones criticas de usuario (Stake, Unstake, ClaimRewards) facilitando indexacion off-chain.

▼ Top 3 Gaps Criticos

  • Sin especificacion de formulas aritmeticas: la funcion _calcRewardPerToken() carece de precision analysis documentada.
  • Owner puede modificar rewardRate sin timelock; riesgo de rug pull o penalizacion accidental a stakers activos.
  • Solo 62 tests sin cobertura branch; cero fuzzing ni CI/CD de tests automatizados en Pull Requests.
Scorecard de Madurez — 9 Categorias
Categoria
Rating
Puntuacion
Hallazgo clave
01
Aritmetica
WEAK
1 / 4
Sin especificacion de formulas; assembly en MathLib sin precision analysis
02
Auditoria
WEAK
1 / 4
Eventos de usuario pero sin eventos de cambio de parametros; sin monitoreo off-chain
03
Auth / Accesos
MODERATE
2 / 4
OZ AccessControl bien usado; falta separacion OPERATOR/PAUSER y tests de compromiso de clave
04
Complejidad
MODERATE
2 / 4
NpawsStaking.sol:870 lineas; _processUnstake() con CC=17; logica de gobernanza duplicada
05
Descentralizacion
WEAK
1 / 4
Owner EOA unico; sin timelock en cambios de rewardRate; sin multisig; sin opt-out de usuario
06
Documentacion
MODERATE
2 / 4
README presente; sin NatSpec sistematico; sin diagrama de arquitectura ni glosario de dominio
07
Riesgos MEV / Ordering
SATISFACTORY
3 / 4
Staking sin oracle externo reduce riesgo MEV; bloqueo por bloque en votaciones; sin front-running obvio
08
Codigo de Bajo Nivel
WEAK
1 / 4
Assembly inline en MathLib sin comentarios de justificacion; sin tests especificos de casos limite
09
Testing & Verificacion
WEAK
1 / 4
62 tests unitarios; sin fuzzing; CI/CD solo compila; sin branch coverage ni tests de integracion
Analisis Detallado por Categoria
1
Aritmetica
NpawsRewards.sol · MathLib.sol
WEAK — 1/4

Evidencia Positiva

  • Solidity 0.8.20: overflow nativo sin SafeMath
  • MathLib.sol encapsula operaciones custom
  • Constante PRECISION = 1e18 usada consistentemente

Gaps Identificados

  • Sin especificacion de formula de recompensa
  • Rounding direction no documentada (floor vs ceil)
  • Precision loss en division no analizada
  • Sin test de aritmetica edge-case (staker unico, pool vacio)
// NpawsRewards.sol:143-158function _calcRewardPerToken() internal view returns (uint256) { // Sin especificacion de formula ni analisis de precision uint256 elapsed = block.timestamp - lastUpdateTime; return rewardPerTokenStored + (elapsed * rewardRate * PRECISION) / totalStaked; // RIESGO: division-before-multiplication puede perder precision // No documentado: comportamiento cuando totalStaked → 0 }
Gap critico: La formula de recompensa no tiene documento de especificacion. El calculo elapsed * rewardRate * PRECISION / totalStaked puede acumular errores de redondeo en posiciones grandes. No hay analisis de precision documentado.
Para alcanzar MODERATE: Crear docs/ARITHMETIC_SPEC.md con formula en notacion matematica, rangos esperados, justificacion de rounding, y tests especificos de precision para pool con 1 wei staked.
2
Auditoria & Monitoreo
NpawsStaking.sol · NpawsGovernance.sol
WEAK — 1/4

Eventos Presentes

  • Staked(address, uint256)
  • Unstaked(address, uint256)
  • RewardsClaimed(address, uint256)
  • ProposalCreated / VoteCast

Gaps Criticos

  • RewardRateChanged sin evento
  • Sin monitoreo off-chain (Tenderly/Defender)
  • Sin plan de respuesta a incidentes
  • Cambios de parametro critico no auditables on-chain
Gap critico: La funcion setRewardRate() (NpawsStaking.sol:312) no emite evento. Un cambio malicioso o erroneo de tasa de recompensa seria invisible para indexers y usuarios hasta que revisen el estado.
Para alcanzar MODERATE: Anadir RewardRateUpdated(uint256 old, uint256 new_), desplegar alertas en Tenderly Alerts para cambios de parametros criticos, y documentar runbook de respuesta a incidentes.
5
Descentralizacion
AccessManager.sol · NpawsStaking.sol
WEAK — 1/4

Positivo

  • Estructura de gobernanza on-chain basica
  • Funciones de pausa disponibles

Riesgos de Centralizacion

  • Owner EOA unico controla todo
  • rewardRate modificable instantaneamente
  • Sin multisig (Gnosis Safe)
  • Sin timelock en ningun parametro
  • Usuario no puede hacer opt-out ante upgrade
// NpawsStaking.sol:312-318function setRewardRate(uint256 _newRate) external onlyOwner { rewardRate = _newRate; // Efecto inmediato, sin timelock // RIESGO: owner puede reducir rewardRate a 0 en cualquier momento // sin preaviso a stakers. No hay evento emitido (ver Cat.2). }
Gap critico: Un owner malicioso o comprometido puede drenar las recompensas y cerrar el protocolo en una transaccion. El riesgo de rug pull es alto sin multisig y timelock.
Para alcanzar MODERATE: Desplegar TimelockController (48h) para cambios de rewardRate, migrar owner a Gnosis Safe 2/3, documentar escenarios de compromiso de clave.
8
Codigo de Bajo Nivel
MathLib.sol
WEAK — 1/4

Positivo

  • Assembly limitado a MathLib.sol (aislado)
  • No hay delegatecall ni call de bajo nivel
  • Sin proxies upgradeable complejos

Riesgos

  • 3 bloques assembly sin comentario de justificacion
  • Funcion mulDiv() sin test de overflow boundary
  • Sin auditoria especializada del assembly
// MathLib.sol:67-84 — Assembly sin justificacionfunction mulDiv(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) { assembly { // Sin comentario explicando por que se usa assembly aqui // Sin analisis de casos donde d == 0 en assembly let mm := mulmod(x, y, not(0)) let hi := sub(mm, mul(x, y)) // ... 12 lineas mas sin documentar } }
Para alcanzar MODERATE: Anadir comentario NatSpec explicando por que se necesita assembly (optimizacion de gas cuantificada), agregar require(d != 0) antes del bloque, y tests de boundary para x=type(uint256).max.
9
Testing & Verificacion
test/NpawsStaking.test.ts · test/NpawsRewards.test.ts
WEAK — 1/4

Positivo

  • 62 tests unitarios en Hardhat
  • Happy-path cubierto para stake/unstake/claim
  • Compilacion y lint en CI/CD

Gaps Criticos

  • Sin fuzzing (Echidna / Foundry fuzz)
  • Branch coverage estimada <40%
  • CI no ejecuta tests en PRs
  • Sin tests de integracion multicontrato
  • Sin test de escenario de pausa/emergencia
Gap critico: El CI/CD solo ejecuta hardhat compile y ESLint en Pull Requests. Los tests no se ejecutan automaticamente, lo que significa que codigo roto puede llegar a main sin deteccion.
Para alcanzar MODERATE: Anadir npx hardhat test --coverage en el CI de PR, alcanzar 80% line coverage, e implementar al menos 5 invariantes con Echidna (rewardPerToken monotonamente creciente, totalStaked = sum(balances)).
7
Riesgos MEV / Ordenacion de Transacciones
NpawsGovernance.sol · NpawsStaking.sol
SATISFACTORY — 3/4

Fortalezas

  • Sin oracle externo: riesgo MEV reducido nativamente
  • Votacion bloqueada por bloque (snapshot pre-propuesta)
  • Recompensas calculadas por tiempo (no por precio)
  • Sin swap/AMM integrado: no hay front-running de precio

Mejoras Posibles

  • Documentar analisis MEV formalmente
  • Considerar commit-reveal para votaciones sensibles
Para alcanzar STRONG: Anadir docs/MEV_ANALYSIS.md documentando los riesgos identificados y descartados, y evaluar commit-reveal scheme si las propuestas de gobernanza fuesen sobre parametros economicos sensibles.
Hoja de Ruta de Mejoras Priorizadas
CRITICO Resolver antes de mainnet (Semana 1-2)
1

Desplegar TimelockController en cambios de rewardRate

El mayor riesgo de confianza del protocolo. Un owner EOA puede cambiar la tasa instantaneamente. Timelock de 48h da tiempo a stakers para reaccionar.

  • Desplegar OZ TimelockController con delay = 48 horas
  • Migrar ownership de NpawsStaking a TimelockController
  • Migrar owner EOA a Gnosis Safe 2/3 como proposer
  • Documentar procedimiento de emergencia (pause sin timelock)
3-4 dias ↑ Descentralizacion: WEAK → MODERATE
2

Activar tests en CI/CD y alcanzar 80% line coverage

El pipeline actual no ejecuta tests en PRs. Esto permite que regresiones criticas lleguen a produccion sin deteccion automatica.

  • Anadir job test en .github/workflows: npx hardhat test --coverage
  • Configurar threshold de cobertura minima al 80%
  • Anadir tests para ramas de error (revert conditions)
  • Test de escenario de pausa y emergencia
2-3 dias ↑ Testing: WEAK → MODERATE
ALTA PRIORIDAD Antes de lanzamiento publico (Semana 3-4)
3

Crear especificacion de formulas aritmeticas

La formula de recompensa opera en fixed-point de 18 decimales sin documentar sus invariantes ni casos limite.

  • Crear docs/ARITHMETIC_SPEC.md con formula en notacion matematica
  • Documentar direccion de rounding y justificacion
  • Anadir test: rewardPerToken con totalStaked = 1 wei
  • Comentar cada bloque assembly en MathLib.sol
2-3 dias ↑ Aritmetica: WEAK → MODERATE
4

Anadir eventos de cambio de parametros criticos y monitoreo

Los cambios de configuracion como rewardRate son invisibles on-chain y no generan alertas.

  • Emit RewardRateUpdated(uint256 old, uint256 new_) en setRewardRate()
  • Emit OwnershipTransferred en todos los cambios de rol
  • Desplegar alertas en Tenderly para eventos criticos
  • Crear runbook de respuesta a incidentes en docs/
2-3 dias ↑ Auditoria: WEAK → MODERATE
MEDIA PRIORIDAD Mejoras para V2 (Mes 2-3)
5

Fuzzing con Echidna para invariantes criticos

Los invariantes matematicos del protocolo (rewardPerToken monotono, totalStaked conservado) no estan verificados automaticamente.

  • Implementar 5 invariantes Echidna en contracts/test/
  • rewardPerToken solo crece, nunca decrece
  • sum(stakedBalances) siempre == totalStaked
  • Integrar fuzzing en CI semanal (no bloquea PR)
4-5 dias ↑ Testing: MODERATE → SATISFACTORY
6

Refactorizar NpawsStaking.sol y reducir CC

El contrato principal tiene 870 lineas y _processUnstake() con complejidad ciclomatica 17. Dificulta auditoria y aumenta riesgo de bugs.

  • Extraer logica de rewards a libreria StakingMath
  • Dividir _processUnstake() en 3 funciones internas
  • Eliminar duplicacion con NpawsGovernance.sol
  • Anadir NatSpec completo a todas las funciones publicas
5-7 dias ↑ Complejidad: MODERATE → SATISFACTORY

Conclusion

El protocolo NPAWS muestra una madurez global de 1.7/4.0 (WEAK-MODERATE), con 5 categorias en nivel WEAK que representan riesgos concretos antes de un lanzamiento en mainnet. La mayor amenaza es la centralizacion con owner EOA sin timelock, que expone a los stakers a cambios unilaterales de tasa de recompensa sin preaviso.

La buena noticia: los problemas son tecnicamente resolubles en 3-4 semanas con las mejoras CRITICAS y ALTA PRIORIDAD del roadmap. El punto de partida es solido (Solidity moderno, OZ AccessControl, separacion de contratos) y la categoria MEV esta bien resuelta de forma natural por el diseno del protocolo.

Recomendacion: Completar items CRITICOS (timelock + CI/CD) antes de cualquier comunicacion publica o auditoria externa. Una auditoria formal con estos gaps activos elevaria el coste y el tiempo significativamente.

1
Desplegar Gnosis Safe + TimelockController
2
Activar tests en CI y alcanzar 80% coverage
3
Redactar ARITHMETIC_SPEC.md y comentar assembly
4
Anadir eventos criticos y monitoreo Tenderly
5
Auditoria externa (Trail of Bits / Code4rena)